Shader Lab코드구조 |
// 쉐이더 이름이라고 생각하면 된다.
// 특수문자 / 으로 그룹을 구분한다.
Shader "Example/URPUnlitSimpleVertex" {
Tags {
// Tag는 실행되는 시기와 조건을 정의한다.
}
Properties {
// 속성 값으로 다양한 종류의 피라미터를 넣을 수 있습니다.
// 참조를 위한 이름과 표시될 이름을 작성하고 값을 입력합니다.
// 텍스쳐, 색, 백터 등 다른 값들을 여기에 배치함
// 유니티 Inspector 창에서 입력값을 조절할 수 있는 값 지정
}
SubShader {
// 여기에 3가지 유형의 세이더를 작성합니다.
// 표면세이더, 프로그먼트 쉐이더, 고정쉐이더
}
SubShader {
// SubShader를 추가할 수 있다.
// 아래에 추가할수록 하위 버전의 디바이스를 위한 쉐이더이다.
// 오래된 그래픽 카드에서 돌아갈 수 있도록 하기위해서 작성
Pass {
// 물체를 그릴 때 GPU에게 넘겨줄(pass) 작업을 기술하는 곳.
// pass가 두개이상이면 멀티패스라고 부르며 두 번에 걸쳐 그린다.
}
}
Fallback "Diffuse" // 하위버전마저 힘들다면, 가장 낮은 품질로 처리.
}
쉐이더 이름 바꾸기 |
Shader "Example/URPUnlitSimpleVertex" 이 부분이 유니티에서 아래와 같이 나온다.
Tag |
Tags {
//투명도가 없음(Opaque)
"RenderType" = "Opaque"
//파이프라인 대상
"RenderPipeline" = "UniversalRenderPipeline"
//랜더링 대기순서
"Queue" = "Background"
}
Properties |
Properties는 변수를 지정하는 곳이다.
변수명 ("인스펙터에 보여지는 이름", 데이터타입) = 데이터 타입에 초기 값
Shader "Example/URPUnlitSimpleVertex" {
Properties {
_MyColor ("Green Color", Color) = (0, 1, 0, 1)
_VertexCount ("display name", Int) = number
_MaxValue ("display name", Vector) = (number,number,number,number)
_MyTexture ("My Texture", 2D) = "white" { }
}
}
SubShader |
Shader "Example/URPUnlitSimpleVertex" {
SubShader{
Pass {
// vertex를 정의 (점의 위치를 결정)
#pragma vertex vert
// fragment를 정의 (픽셀의 색상을 결정)
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
// 정점 셰이더 입력 구조
struct Attributes {
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
};
}
}
}
▷ SubShader
여러개를 지정할 수 있습니다.
이를 통하여 다른 빌드 데스크톱(Direct3D), MAC(OpenGL), 모바일용(OpenGL ES), 안드로이드(vulkan), 아이폰(Metal)등의 플랫폼에 대응할 수 있습니다.
또한 Direct 9, DirectX 10과 같이 다른 버전이라도 SubShader을 추가하여 대응할 수 있습니다.
Unity에서 컴파일할 타겟을 설정하거나 볼 수 있습니다.
▷ Pass
실질적으로 랜더링되는 영역입니다.
여러개의 Pass를 가질 수 있지만 여러번 랜더링 되므로 더 많은 자원을 소모합니다.
▷ #paragma
paragma는 그리스어에서 유래했으며 유니티에서 스니핏(snippet)이라고도 불립니다.
조치 또는 수행해야 할 일을 나타냅니다.
셰이더의 조명 계산 설정, 기타 세부적인 분기를 정해주며 전처리(Preprocessing)라고 할 수 있습니다.
▷ #include
자주 사용되는 HLSL 매크로와 함수를 현재 작성하는 스크립트에 넣는 기능입니다.
다른 HLSL파일에 대한 참조도 포함되어 있습니다.
- UnityShaderVariables.cginc
변환, 카메라 및 조명 데이터와 같이 렌더링에 필요한 전체 셰이더 변수를 정의합니다.필요한 경우 모두 Unity에서 설정합니다.
- HLSLSupport.cginc
대상 플랫폼에 관계없이 동일한 코드를 사용할 수 있도록 설정합니다. 따라서 플랫폼 별 데이터 유형 등을 사용하는 것에 대해 걱정할 필요가 없습니다.
- UnityInstancing.cginc
드로 콜을 줄이기위한 특정 렌더링 기술인 인스턴스 지원을위한 것입니다. 파일을 직접 포함하지는 않지만 UnityShaderVariables에 따라 다릅니다 .
▷ struct
하나이상의 변수를 묶어서 새로운 자료형을 정의합니다.
예제1 |
기본 셰이더 값은 아래와 같습니다.
메쉬를 흰색으로 랜더링 합니다.
Render Queue는 Geometry의 기본값인 2000
양면 전역 조명을 활성화하는 토글이 있습니다.
Shader "StudySRP/Catlike1"
{
Properties{}
SubShader{
Pass {}
}
}
예제2 |
SV_TARGET과 SV_POSITION은 랜더 대상에 대한 시스템 기본값을 제공합니다.
현재 모든 정점이 0으로 설정되면 메시가 한 지점으로 축소되고 아무것도 렌더링되지 않습니다.
SV는 시스템 값을 나타내고 Position은 최종 정점위치를 나타냅니다.
어디서 가져오는지 궁금하다면 아래쪽에서 확인가능합니다.
{unity 설치 경로} /Data/CGIncludes/HLSLSupport.cginc
Shader "StudySRP/Catlike1"
{
Properties{}
SubShader{
Pass {
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Catlike1Pass.hlsl"
#ifndef CUSTOM_UNLIT_PASS_INCLUDED
#define CUSTOM_UNLIT_PASS_INCLUDED
#endif
float4 vert() : SV_POSITION {
return 0.0;
}
float4 frag() : SV_TARGET{
return 0.0;
}
ENDHLSL
}
}
}
예제3 |
float3 positionOS : POSITION를 통하여 공간위치를 나타내면 위와 같습니다.
출력한 위치가 잘못된 공간에 있기때문에 이렇게 출력됩니다.
Shader "StudySRP/Catlike1"
{
Properties{}
SubShader{
Pass {
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Catlike1Pass.hlsl"
#ifndef CUSTOM_UNLIT_PASS_INCLUDED
#define CUSTOM_UNLIT_PASS_INCLUDED
#endif
float4 vert(float3 positionOS : POSITION) : SV_POSITION {
return float4(positionOS, 1.0);
}
float4 frag() : SV_TARGET{
return 0.0;
}
ENDHLSL
}
}
}
예제4 |
정확하게 그리려면 무언가가 그려질 때 GPU로 전송되는 행렬이필요합니다.
// 객체 행렬을 가져오고
float4x4 unity_ObjectToWorld;
//객체를 월드 공간으로 변환시킵니다.
float3 TransformObjectToWorld (float3 positionOS) {
return mul(unity_ObjectToWorld, float4(positionOS, 1.0)).xyz;
}
// 월드공간에 투영 행렬을 곱하여 보여지는 정확한 좌표를 구합니다.
float4 TransformWorldToHClip (float3 positionWS) {
return mul(unity_MatrixVP, float4(positionWS, 1.0));
}
Shader "StudySRP/Catlike1"
{
Properties{}
SubShader{
Pass {
HLSLPROGRAM
#ifndef CUSTOM_UNITY_INPUT_INCLUDED
#define CUSTOM_UNITY_INPUT_INCLUDED
float4x4 unity_ObjectToWorld;
float4x4 unity_MatrixVP;
#endif
#ifndef CUSTOM_COMMON_INCLUDED
#define CUSTOM_COMMON_INCLUDED
#include "UnityInput.hlsl"
float3 TransformObjectToWorld(float3 positionOS) {
return mul(unity_ObjectToWorld, float4(positionOS, 1.0)).xyz;
}
float4 TransformWorldToHClip(float3 positionWS) {
return mul(unity_MatrixVP, float4(positionWS, 1.0));
}
#endif
#pragma vertex vert
#pragma fragment frag
#include "Catlike1Pass.hlsl"
#ifndef CUSTOM_UNLIT_PASS_INCLUDED
#define CUSTOM_UNLIT_PASS_INCLUDED
#endif
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
float4 vert(float3 positionOS : POSITION) : SV_POSITION {
float3 positionWS = TransformObjectToWorld(positionOS.xyz);
return TransformWorldToHClip(positionWS);
}
float4 frag() : SV_TARGET{
return 0.0;
}
ENDHLSL
}
}
}
예제5 |
이제까지 정의한 기능은 이미 유니티에서 구현되어 있습니다 ^-^. (나만 삽질할 수없지)
float3 TransformObjectToWorld(float3 positionOS) { return mul(unity_ObjectToWorld, float4(positionOS, 1.0)).xyz; } float4 TransformWorldToHClip(float3 positionWS) { return mul(unity_MatrixVP, float4(positionWS, 1.0)); } |
위의 함수를 정의를 지우고 SpaceTransform.hlsl를 추가합니다.
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl"
위의 변수를 지우고 아래의 오브젝트 정의를 추가합니다.
#define UNITY_MATRIX_M unity_ObjectToWorld
그리고 역행렬을 대신할 정의를 더 추가해야합니다. 사용하지 않더라도 추가안하면 에러 ㅠㅠ
#define UNITY_MATRIX_I_M unity_WorldToObject
#define UNITY_MATRIX_V unity_MatrixV
#define UNITY_MATRIX_VP unity_MatrixVP
#define UNITY_MATRIX_P glstate_matrix_projection
이제 정의된 값에 대응한 변수를 추가해야합니다.
float4x4 unity_ObjectToWorld;
float4x4 unity_WorldToObject;
real4 unity_WorldTransformParams;
float4x4 unity_MatrixVP;
float4x4 unity_MatrixV;
float4x4 glstate_matrix_projection;
여기서 뜬금없이 real4 라는 정의 벡터가 나오는데 이에 대하여 궁금하다면 아래의 경로를 살펴보면 됩니다.
Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl
Shader "StudySRP/Catlike1"
{
Properties{}
SubShader{
Pass {
HLSLPROGRAM
#include "Catlike1Pass.hlsl"
#include "UnityInput.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#define UNITY_MATRIX_M unity_ObjectToWorld
#define UNITY_MATRIX_I_M unity_WorldToObject
#define UNITY_MATRIX_V unity_MatrixV
#define UNITY_MATRIX_VP unity_MatrixVP
#define UNITY_MATRIX_P glstate_matrix_projection
#ifndef CUSTOM_UNITY_INPUT_INCLUDED
#define CUSTOM_UNITY_INPUT_INCLUDED
float4x4 unity_ObjectToWorld;
float4x4 unity_WorldToObject;
real4 unity_WorldTransformParams;
float4x4 unity_MatrixVP;
float4x4 unity_MatrixV;
float4x4 glstate_matrix_projection;
#endif
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl"
#pragma vertex vert
#pragma fragment frag
#ifndef CUSTOM_UNLIT_PASS_INCLUDED
#define CUSTOM_UNLIT_PASS_INCLUDED
#endif
float4 vert(float3 positionOS : POSITION) : SV_POSITION {
float3 positionWS = TransformObjectToWorld(positionOS.xyz);
return TransformWorldToHClip(positionWS);
}
float4 frag() : SV_TARGET{
return 0.0;
}
ENDHLSL
}
}
}
HLSL 기본예제 사용해보기. |
Shader "Example/URPUnlitSimpleVertex"
{
Properties{
//인스펙터에 색상지정아이콘 띄어주고 초록색을 설정
_MyColor("Green Color", Color) = (0, 1, 0, 1)
//익스펙터에 슬라이드바를 띄어주고 범위는 -0.001부터 0.001까지 기본값은 0
_Amount("Extrusion", Range(-0.001,0.001)) = 0
}
SubShader{
Tags {
"RenderType" = "Opaque"
"RenderPipeline" = "UniversalRenderPipeline"
"Queue" = "Background"
}
Pass{
//HLSL 시작을 선언하고
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
// Properties에서 선언한 변수들 HLSL에서 사용할 수 있게 할당
CBUFFER_START(UnityPerMaterial)
half4 _MyColor;
half _Amount;
CBUFFER_END
// 정점 셰이더 입력 구조
struct Attributes {
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
};
// 정점 출력데이터 출력 구조
struct Varyings{
float4 positionHCS : SV_POSITION;
float3 normalWS : NORMAL;
};
// vertex(점) 위치 정의하기
Varyings vert(Attributes IN){
// OUT객체 선언.
Varyings OUT;
// 객체 공간에서 균질공간으로 변환
OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
// 변환된 값 반환.
return OUT;
}
half4 frag() : SV_Target{
// 색상을 정의하고
half4 customColor;
// 색상 집어넣기.
customColor = _MyColor;
// 색상 반환하여 적용.
return customColor;
}
ENDHLSL
}
}
}