使用着色器多样体处理多种情况#pragma multi_compile #pragma shader_feature

支持条件编译的编译型语言,通常是使用预处理宏的机制确定宏的取值,然后编译器根据宏的值
决定编译代码中的哪一部分。

通过使用编译指示符#pragma multi_compile或者#pragma shader_feature,结合判定宏是否启用的指令defined,还有引擎C#语言层的Material类成员函数EnableKeyworld或者Shader类静态成员函数EnableKeyword,
Unity3D的着色器编译器也支持这种预处理机制。

每一段由编译条件控制编译与否的代码段称为着色器多样体(shader variants),#pragma multi_compile或者#pragma shader_feature指示符后面跟着的名字字符串称为多样体关键字(variants keyword)。多样体关键字在着色器源代码中使用define、#ifdef等进行判断,称为多样体预处理宏(variants preprocess macro)。

#pragma multi_compile和#pragma shader_feature的区别:
如:
#pragma multi_compile FANCY_STUFF_OFF FANCY_STUFF_ON
该语句将会生成两个着色器多样体,一种就是启用了FANCY_STUFF_OFF,另一种是FANCY_STUFF_ON。
在C#语言层面,调用Material类的成员函数EnableKeyword可以显示地激活其中一个着色器多样体,如果没有一个多样体关键字被显示地启用。那么将默认启用第一个多样体。#pragma multi_compile还可以定义多于两个的多样体关键字。

当使用完全由下划线"_"组成的多样体关键字时,对应的多样体依然被编译,但没有与之对应的预处理宏被定义,比如:
#pragma multi_compile FOO_ON
在着色器代码中就不能使用defined(
)这样的语句去判断某代码是否开启。
但是“__”对应的着色器多样提会被识别并编译。例如:

float4 FooFunction()
{
	#ifdef FOO_ON
		return float4(1,0,0,1);
	#else
		return float4(1,1,0,1);
	#endif
}

如果没有调用EnableKeyword函数,去启用FOO_ON,那么调用FooFunction函数时,将会执行#else 和#endif之间的代码段,返回float4(1,1,0,1);

使用这种匿名的方式定义多样体关键字,其好处是可以节省多样体关键字的个数,因为着色器编译器对多样体关键字的定义个数是有限制的。

pragma shader_feature类似于#pragma multi_compile
,唯一的区别是,shader_feature指示符中声明的着色器多样体如果未被使用,在构建游戏运行包(game build)时,将不会打包进去。因此,如果要在物体的材质中设置,即调用Material类成员函数EnableKeyword去设置的多样体关键字,用shader_feature指示符声明最好。如果要在全局范围中设置,即调用Shader类静态方法EnableKeyword去设置的多样体关键字的,用#pragma multi_compile指示符声明最好。

发布了610 篇原创文章 · 获赞 96 · 访问量 33万+

猜你喜欢

转载自blog.csdn.net/wodownload2/article/details/104223134