Unity는 셰이더 프로그램을 컴파일할 때 일부 프리프로세서 매크로를 정의합니다.
매크로: | Target Platform: |
---|---|
SHADER_API_D3D11 |
Direct3D 11 |
SHADER_API_GLCORE |
데스크톱 OpenGL “core”(GL 3/4) |
SHADER_API_GLES |
OpenGL ES 2.0 |
SHADER_API_GLES3 |
OpenGL ES 3.0/3.1 |
SHADER_API_METAL |
iOS/Mac Metal |
SHADER_API_VULKAN |
Vulkan |
SHADER_API_D3D11_9X |
유니버설 Windows 플랫폼용 Direct3D 11 “기능 수준 9.x” 타겟 |
SHADER_API_DESKTOP |
Windows, Mac, Linux 데스크톱 플랫폼, WebGL, Stadia |
SHADER_API_MOBILE |
iOS 및 Android 모바일 플랫폼, tvOS |
또한 타겟 셰이딩 언어가 GLSL인 경우(OpenGL/GLES 플랫폼에서 항상 참) SHADER_TARGET_GLSL
도 정의됩니다.
SHADER_TARGET
은 셰이더 타겟 컴파일 모델과 일치하는(즉 #pragma target
명령과 일치하는) 숫자 값으로 정의됩니다. 예를 들어, 셰이더 모델 3.0으로 컴파일하는 경우 SHADER_TARGET
은 30
입니다. 셰이더 코드에서 조건부 확인을 수행하기 위해 사용할 수 있습니다. 예제:
# if SHADER_TARGET < 30
// less than Shader model 3.0:
// very limited Shader capabilities, do some approximation
#else
// decent capabilities, do a better thing
#endif
UNITY_VERSION
에는 Unity 버전의 숫자 값이 있습니다.예를 들어 Unity 2020.3.0의 UNITY_VERSION
은 202030
입니다.이는 서로 다른 빌트인 셰이더 기능을 사용하는 셰이더를 작성해야 하는 경우 버전을 비교하는 데 사용할 수 있습니다.예를 들어 #if UNITY_VERSION >= 202000
프리 프로세서 확인은 2020 이상 버전에서만 패스합니다.
SHADER_STAGE_VERTEX
, SHADER_STAGE_FRAGMENT
, SHADER_STAGE_DOMAIN
, SHADER_STAGE_HULL
, SHADER_STAGE_GEOMETRY
, SHADER_STAGE_COMPUTE
프리프로세서 매크로는 각 셰이더 스테이지를 컴파일할 때 정의됩니다. 일반적으로 일부 작업을 약간 다르게 수행해야 하는 경우를 처리하기 위해 픽셀 셰이더와 연산 셰이더 코드를 공유해야 하는 경우에 유용합니다.
이 플랫폼 매크로를 직접 사용하는 것은 장래성을 충분히 보장하지 않기 때문에 권장하지 않습니다. 예를 들어 D3D11를 확인하는 셰이더를 작성하는 경우 나중에 확인을 확장하여 Vulkan이 포함되도록 해야 할 수 있습니다. 대신 Unity는 (HLSLSupport.cginc
에) 헬퍼 매크로를 몇 개 정의합니다.
매크로: | 용도: |
---|---|
UNITY_BRANCH |
실제 브랜치로 컴파일해야 함을 컴파일러에 알리기 위해 조건문 앞에 추가합니다. HLSL 플랫폼에서는 [branch] 로 확장합니다. |
UNITY_FLATTEN |
실제 브랜치 명령을 방지하기 위해 평면화해야 함을 컴파일러에 알리기 위해 조건문 앞에 추가합니다. HLSL 플랫폼에서는 [flatten] 으로 확장합니다. |
UNITY_NO_SCREENSPACE_SHADOWS |
캐스캐이드된 스크린 공간 섀도우맵을 사용하지 않는 플랫폼(모바일 플랫폼)에서 정의합니다. |
UNITY_NO_LINEAR_COLORSPACE |
리니어 색 공간을 지원하지 않는 플랫폼(모바일 플랫폼)에서 정의합니다. |
UNITY_NO_RGBM |
라이트맵용 RGBM 압축을 사용하지 않는 플랫폼(모바일 플랫폼)에서 정의합니다. |
UNITY_NO_DXT5nm |
DXT5nm 노멀 맵 압축을 사용하지 않는 플랫폼(모바일 플랫폼)에서 정의합니다. |
UNITY_FRAMEBUFFER_FETCH_AVAILABLE |
“프레임버퍼 컬러 페치” 기능을 사용할 수 있는 플랫폼(일반적으로 iOS 플랫폼 - OpenGL ES 2.0, 3.0 및 Metal)에서 정의합니다. |
UNITY_USE_RGBA_FOR_POINT_SHADOWS |
점 광원 섀도우맵에 인코딩된 뎁스가 있는 RGBA 텍스처를 사용하는 플랫폼에서 정의합니다. 그 외의 플랫폼에는 싱글 채널 플로팅 포인트 텍스처가 사용됩니다. |
UNITY_ATTEN_CHANNEL |
데이터가 포함된 광원 감쇠 텍스처 채널을 정의하고, 픽셀당 조명 코드에 사용됩니다. ‘r’ 또는 ’a’로 정의됩니다. |
UNITY_HALF_TEXEL_OFFSET |
텍셀을 픽셀에 매핑할 때, 하프 텍셀 오프셋 조정이 필요한 플랫폼에서 정의합니다. |
UNITY_UV_STARTS_AT_TOP |
값이 항상 1 또는 0으로 정의됩니다. 텍스처 “맨 위”의 텍스처 V 좌표가 0인 플랫폼에서는 값이 1입니다. Direct3D와 유사한 플랫폼에서는 1이 값으로 사용되고 OpenGL과 유사한 플랫폼에서는 0이 값으로 사용됩니다. |
UNITY_MIGHT_NOT_HAVE_DEPTH_Texture |
플랫폼에서 수동으로 뎁스를 텍스처로 렌더링하여 섀도우 맵 또는 뎁스 텍스처를 에뮬레이트할 수 있는 경우 정의됩니다. |
UNITY_PROJ_COORD(a) |
컴포넌트가 4개인 벡터가 주어지면 투사된 텍스처 읽기에 적합한 텍스처 좌표를 반환합니다. 대부분의 플랫폼에서는 주어진 값을 직접 반환합니다. |
UNITY_NEAR_CLIP_VALUE |
근거리 클리핑 평면의 값으로 정의됩니다.Direct3D와 유사한 플랫폼에서는 1.0을 사용하고 OpenGL과 유사한 플랫폼에서는 –1.0을 사용합니다. |
UNITY_VPOS_TYPE |
픽셀 포지션 입력(VPOS)에 요구되는 데이터 타입을 정의합니다. D3D9에서는 float2 고 그 외의 경우 float4 입니다. |
UNITY_CAN_COMPILE_TESSELLATION |
셰이더 컴파일러가 테셀레이션 셰이더 HLSL 구문을 이해하는 경우에 정의됩니다(현재 D3D11에만 해당). |
UNITY_INITIALIZE_OUTPUT(type,name) |
주어진 타입 의 변수 이름 을 영(0)으로 초기화합니다. |
UNITY_COMPILER_HLSL , UNITY_COMPILER_HLSL2GLSL , UNITY_COMPILER_CG
|
셰이더를 컴파일하는 데 사용되는 셰이더 컴파일러를 나타냅니다. 자세한 내용은 셰이더 컴파일 문서를 참조하십시오. 컴파일러 간 차이를 다루는 매우 구체적인 셰이더 구문에 직면하는 경우에 각 컴파일러마다 다른 코드를 작성하려면 사용합니다. |
UNITY_REVERSED_Z
- 리버스 Z 버퍼를 사용하는 플랫폼에서 정의합니다. 저장되는 Z 값의 범위는 10이 아니라 01입니다.플랫폼에 따라 섀도우 맵을 선언하고 샘플링하는 방법이 크게 다를 수 있습니다. Unity에는 이 작업에 유용한 매크로가 몇 개 있습니다.
매크로: | 용도: |
---|---|
UNITY_DECLARE_SHADOWMAP(tex) |
이름이 “tex”인 섀도우맵 텍스처 변수를 선언합니다. |
UNITY_SAMPLE_SHADOW(tex,uv) |
주어진 “uv” 좌표에서 “tex” 섀도우맵 텍스처를 샘플링합니다. XY 컴포넌트는 텍스처 위치이며, Z 컴포넌트는 비교할 뎁스입니다. 섀도우 텀 범위가 01인 플로트 값을 1개 반환합니다. |
UNITY_SAMPLE_SHADOW_PROJ(tex,uv) |
위와 유사하나, 투사 섀도우맵 읽기를 수행합니다. “uv”는 float4이고 나머지 컴포넌트는 룩업 수행을 위해 .w로 나눕니다. |
참고: 모든 그래픽 카드가 섀도우맵을 지원하지는 않습니다. SystemInfo.SupportsRenderTextureFormat을 사용하여 지원 여부를 확인해야 합니다.
Direct3D 11은 모든 셰이더 변수를 “상수 버퍼”로 그룹화합니다. Unity에 내장된 변수는 대부분 이미 그룹화되어 있지만, 자체 셰이더에 있는 변수의 경우 예상 업데이트 빈도에 따라 개별 상수 버퍼에 넣는 것이 더 최적일 수 있습니다.
이렇게 하려면 CBUFFER_START(name)
및 CBUFFER_END
매크로를 사용해야 합니다.
CBUFFER_START(MyRarelyUpdatedVariables)
float4 _SomeGlobalValue;
CBUFFER_END
GPU 컴퓨트 버퍼 또는 그래픽스 버퍼를 사용하여 변수 값을 설정하는 경우, 빌드하는 모든 그래픽스 API에서 버퍼와 상수 버퍼의 데이터 레이아웃이 일치하는지 확인합니다.자세한 내용은 GPU 버퍼와 함께 상수 버퍼 사용을 참조하십시오.
일반적으로 셰이더 코드에 texture2D
를 사용하여 텍스처 및 샘플러 페어를 선언합니다. 하지만 일부 플랫폼(예: DX11)에서는 텍스처와 샘플러가 별도 오브젝트이고, 최대 가능 샘플러 수가 매우 제한적입니다. Unity에는 샘플러 없이 텍스처를 선언하고 다른 텍스처의 샘플러를 사용하여 텍스처를 샘플링하는 매크로가 몇 개 있습니다. 샘플러 제한에 부딪히는 경우 일부 텍스처가 실제로 샘플러를 공유한다는 것을 알고 있다면 매크로를 사용하십시오. (샘플러는 텍스처 필터링 및 래핑 모드를 정의합니다.)
매크로: | 용도: |
---|---|
UNITY_DECLARE_TEX2D(name) |
텍스처 및 샘플러 페어를 선언합니다. |
UNITY_DECLARE_TEX2D_NOSAMPLER(name) |
샘플러 없이 텍스처를 선언합니다. |
UNITY_DECLARE_TEX2DARRAY(name) |
텍스처 배열 샘플러 변수를 선언합니다. |
UNITY_SAMPLE_TEX2D(name,uv) |
주어진 텍스처 좌표를 사용하여 텍스처와 샘플러 페어에서 얻은 샘플입니다. |
UNITY_SAMPLE_TEX2D_SAMPLER( name,samplername,uv) |
다른 텍스처의 샘플러(samplername)를 사용해 텍스처에서 얻은 샘플(name)입니다. |
UNITY_SAMPLE_TEX2DARRAY(name,uv) |
float3 UV가 있는 텍스처 배열에서 얻은 샘플입니다. 좌표의 Z 컴포넌트는 배열 요소 인덱스입니다. |
UNITY_SAMPLE_TEX2DARRAY_LOD(name,uv,lod) |
명시적인 밉맵 레벨이 있는 텍스처 배열에서 얻은 샘플입니다. |
자세한 내용은 샘플러 상태에 대한 문서를 참조하십시오.
표면 셰이더는 컴파일될 때 다양한 패스를 위한 코드를 많이 생성하여 조명을 수행합니다. 각 패스를 컴파일할 때 다음 매크로 중 하나가 정의됩니다.
매크로: | 용도: |
---|---|
UNITY_PASS_FORWARDBASE |
포워드 렌더링 베이스 패스(주방향 광원, 라이트맵, SH) |
UNITY_PASS_FORWARDADD |
포워드 렌더링 추가 패스(패스당 광원 하나) |
UNITY_PASS_DEFERRED |
디퍼드 셰이딩 패스(G버퍼 렌더링) |
UNITY_PASS_SHADOWCASTER |
섀도우 캐스터 및 뎁스 텍스처 렌더링 패스 |
UNITY_SHADER_NO_UPGRADE
를 사용하여 Unity가 셰이더 파일을 자동으로 업그레이드하거나 수정할 수 없도록 설정할 수 있습니다.
뎁스 텍스처는 대부분의 경우 카메라에서 뎁스를 렌더링하는 데 사용됩니다. UnityCG.cginc 포함 파일에는 이 사례에서 위의 복잡성을 처리하는 매크로가 몇 개 있습니다.
참고: DX11/12 및 Metal에서 Z 버퍼 범위는 1–0이고 UNITY_REVERSED_Z가 정의됩니다. 다른 플랫폼에서 범위는 0–1입니다.
예를 들어, 다음 셰이더는 게임 오브젝트의 뎁스를 렌더링합니다.
Shader "Render Depth" {
SubShader {
Tags { "RenderType"="Opaque" }
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 pos : SV_POSITION;
float2 depth : TEXCOORD0;
};
v2f vert (appdata_base v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
UNITY_TRANSFER_DEPTH(o.depth);
return o;
}
half4 frag(v2f i) : SV_Target {
UNITY_OUTPUT_DEPTH(i.depth);
}
ENDCG
}
}
}