셰이더 코드 조각 대부분을 고정시키되 약간 다른 셰이더 “배리언트”가 생성될 수 있게 하면 편리합니다. 일반적으로 “메가 셰이더” 또는 “우버 셰이더”라고 하며, 각 경우마다 다른 프리프로세서 명령으로 셰이더 코드를 여러 번 컴파일할 수 있습니다.
Unity에서는 #pragma multi_compile
또는 #pragma shader_feature
명령을 셰이더 스니핏에 추가하여 이렇게 할 수 있습니다. 표면 셰이더에서도 가능합니다.
런타임 시 적절한 셰이더 배리언트는 머티리얼 키워드(Material.EnableKeyword 및 DisableKeyword) 또는 전역 셰이더 키워드(Shader.EnableKeyword 및 DisableKeyword)에서 선택됩니다.
명령은 다음과 같습니다.
#pragma multi_compile FANCY_STUFF_OFF FANCY_STUFF_ON
하나는 FANCY_STUFF_OFF
가 정의되고 다른 하나는 FANCY_STUFF_ON
이 정의된 두 가지 셰이더 배리언트를 생성합니다. 머티리얼 및 전역 셰이더 키워드에 따라 런타임 시점에 둘 중 하나가 활성화됩니다. 두 키워드가 모두 활성화되지 않는 경우 전자(“off”)가 사용됩니다.
multi\_compile 줄에 키워드가 두 개보다 많을 수 있습니다. 예를 들어, 다음은 네 가지 셰이더 배리언트를 생성합니다.
#pragma multi_compile SIMPLE_SHADING BETTER_SHADING GOOD_SHADING BEST_SHADING
모두 밑줄 처리된 이름이 있으면 프리프로세서 매크로가 정의되지 않은 셰이더 배리언트가 생성됩니다. 이 배리언트는 일반적으로 셰이더 기능에 사용하여 키워드 2개를 모두 소진하는 것을 방지합니다(키워드 제한에 대한 아래 참고 사항 참조). 예를 들어, 다음은 셰이더 배리언트를 아무 것도 정의되지 않은 것과 FOO_ON
이 정의된 것을 하나씩 포함해 총 2개 생성하는 명령입니다.
#pragma multi_compile __ FOO_ON
#pragma shader_feature
는 #pragma multi_compile
과 매우 유사하고 shader\feature 셰이더의 사용되지 않는 배리언트가 게임 빌드에 포함되지 않는다는 유일한 차이점이 있습니다. 따라서 shader\feature는 머티리얼에 설정되는 키워드에 가장 적합하고 multi\_compile은 코드에서 전역으로 설정되는 키워드에 적합합니다.
또한 키워드가 하나뿐인 짧은 표기도 있습니다.
#pragma shader_feature FANCY_STUFF
이 표기는 #pragma shader_feature _ FANCY_STUFF
의 단축키로, 두 셰이더 배리언트로 확장됩니다(첫 번째는 정의가 없고 두 번째는 정의가 있음).
여러 multi_compile 줄이 제공될 수 있고, 결과 셰이더가 가능한 모든 줄 조합에 대해 컴파일됩니다.
#pragma multi_compile A B C
#pragma multi_compile D E
첫 번째 줄에서 세 가지 배리언트가 생성되고, 두 번째 줄에서 두 가지 배리언트가 생성되어 총 여섯 가지의 셰이더 배리언트(A+D, B+D, C+D, A+E, B+E, C+E)가 생성됩니다.
각 multi\compile 줄이 셰이더 “기능” 하나를 제어한다고 생각하면 가장 이해하기 쉽습니다. 이 방법을 사용하면 전체 셰이더 배리언트 수가 매우 빠르게 증가합니다. 예를 들어, 옵션이 각각 두 개인 multi\compile “기능”이 열 개가 있으면 셰이더 배리언트가 총 1,024개 생성됩니다.
When using shader variants, you should bear in mind that there is a limit of 128 keywords in Unity and a few of these are used internally and therefore subtract from the limit. Also, the keywords are enabled globally throughout a particular Unity project so you should be careful not to exceed the limit when multiple keywords are defined in several different shaders.
여러 셰이더 배리언트를 컴파일하는 데 사용되는 “단축키” 표기가 몇 개 있으며, 주로 Unity의 다양한 광원, 섀도우, 라이트맵을 처리하는 데 사용됩니다. 자세한 내용은 렌더링 파이프라인을 참조하십시오.
multi_compile_fwdbase
은 ForwardBase
(포워드 렌더링 베이스) 패스 타입에 필요한 모든 배리언트를 컴파일합니다. 각 배리언트는 다양한 라이트맵 타입과 섀도우가 켜지거나 꺼진 주 방향 광원을 처리합니다.multi_compile_fwdadd
는 ForwardAdd
(포워드 렌더링 추가) 패스 타입의 배리언트를 컴파일합니다. 방형광, 스폿 광원 또는 점 광원 타입과 쿠키 텍스처가 있는 각각의 배리언트를 처리하도록 배리언트를 컴파일합니다.multi_compile_fwdadd_fullshadows
- 위와 동일하지만, 광원이 실시간 섀도우를 표시하는 기능도 포함합니다.multi_compile_fog
는 다양한 안개 타입(off/linear/exp/exp2)을 처리하는 여러 배리언트로 확장됩니다.Most of the built-in shortcuts result in quite many shader variants. It is possible to skip compiling some of them if you know they are not neeeded, by using #pragma skip_variants
. For example:
#pragma multi_compile_fwdadd
// will make all variants containing
// "POINT" or "POINT_COOKIE" be skipped
#pragma skip_variants POINT POINT_COOKIE
One common reason to need shader variants is to create fallbacks or simplified shaders to be able to efficiently run on both high and low end hardware within a single target platform - such as OpenGL ES. To provide a specially optimised set of variants for different levels of hardware capability, you can use shader hardware variants.
셰이더 하드웨어 배리언트 생성을 활성화하려면 #pragma hardware_tier_variants renderer
를 추가합니다. 여기서 renderer
는 셰이더 프로그램 pragma에 사용 가능한 렌더링 플랫폼 중 하나입니다. 이#pragma
로 다른 키워드에 관계없이 셰이더 배리언트가 각 셰이더마다 3개씩 생성됩니다. 각 배리언트에는 다음 중 하나가 정의됩니다.
UNITY_HARDWARE_TIER1
UNITY_HARDWARE_TIER2
UNITY_HARDWARE_TIER3
위 정의를 사용하여 조건부 폴백이나 로우엔드 또는 하이엔드용 추가 기능을 작성할 수 있습니다. 에디터에서 각 티어 간에 전환할 수 있는 그래픽스 에뮬레이션 메뉴를 사용하여 티어를 테스트할 수 있습니다.
To help keep the impact of these variants as small as possible, only one set of shaders is ever loaded in the player. In addition, any shaders which end up identical - for example if you only write a specialised version for TIER1 and all others are the same - then these shaders will not take up any extra space on disk.
At load time Unity will examine the GPU that it is using and auto-detect a tier value, with a default fallback to the highest tier if the GPU is not auto-detected. You can override this tier value by setting Shader.globalShaderHardwareTier
, however this must be done before any shaders you want to vary are loaded - once the shaders are loaded they will have selected their set of variants and this value will have no effect. A good place to set this would be in a pre-load scene before you load your main scene.
이런 셰이더 하드웨어 티어는 플레이어의 품질 설정과 관련이 없고, 전적으로 플레이어를 실행하는 GPU의 상대적인 성능을 통해 인식됩니다.