1.静态分支
2.动态分支
3.变体
1.静态分支
a.静态分支是什么在Shader编写时使用的#if, #ifdef等预处理指令; 它的判断条件是在shader编译时就能确定的宏定义(如UNITY_EDITOR, SHADER_API_MOBILE)b.何时执行在unity编译shader代码之前, unity的shader编译器会先处理这些#if指令, 根据条件的真假将符合条件的代码包含进来, 不符合条件的代码彻底丢弃, 然后进行编译c.目的为了针对不同的环境(如平台, unity版本, 渲染路径)编写一份shader源码, 但为每个环节编译出最合适的shader代码d.性能零运行时开销, 因为判断发生在编译前, 最终生成的shader代码里根本没有被排除的代码

2.动态分支
a.动态分支是什么在Shader代码(CG/HLSL)中使用的if/else语句, 它的判断条件是在GPU上运行时才能确定的变量b.何时执行在GPU渲染每一帧, 每一个顶点或片元的时候c.目的根据运行时的具体情况改变像素的渲染效果d.性能, 有运行时开销, 并且可能很高- GPU的并行架构, GPU并行处理大量数据(比如32个片元), 如果这32个片元在动态分支中走了不同的路径, 所有路径的代码GPU都必须执行, 然后丢弃不需要的结果; 这被称为分歧, 会严重降低并行效率- 最佳情况, 如果同一个线程束内的所有数据都走同一个分支, 性能损耗比较小

为什么if语句最好不要在片元着色器中执行?
3.变体
a.变体是什么这是静态分支的直接产物, 当你使用#if和#pragma multi_compile或#pragmashader_feature时, Unity会为每一种可能的宏组合预先编译好多个版本的Shader代码; 每一个版本就是一个变体(Variant)b.如何产生通过#pragma multi_compile或#pragma shader_feature指令; 你定义一些关键字(ke yword), Unity会为这些关键字所有可能的组合都编译一个Shader变体c.目的在运行时通过Material.EnableKeyword("A")来切换不同的Shader功能, 而切换的开销极低(只是切换一个已经编译好的子程序); 常用于不同的材质配置, 如是否有凹凸贴图、是否开启镜面反射等d.代价, 变体爆炸(Variant Explosion), 关键字越多, 变体的数量会呈指数级增长; 这会导致- 构建时间变长: Unity需要编译很多个变体- 构建体积变大: 所有变体都会被打包到游戏里- 内存占用增加: 即使你只用了一个变体, 运行时也可能需要加载整个ShaderLab对象, 它包含了所有变体的信息