【Unity3D】Shader变体管理流程-变体剔除

一、什么是Shader变体管理

  想要回答这个问题,要看看什么是Shader变体。

1. 变体

  我们用ShaderLab编写Unity中的Shader,当我们需要让Shader同时满足多个需求,例如说,这个是否支持阴影,此时就需要加keyword(关键字),例如在代码中#pragma multi_compile SHADOW_ON SHADOW_OFF,对逻辑上有差异的地方用#ifdef SHADOW_ON#if defined(SHADOW_ON)区分(#if defined()的好处是可以有多个条件,用与、或逻辑运算连接起来):

Light mainLight = GetMainLight();
float shadowAtten = 1;
#ifdef SHADOW_ON
    shadowAtten = CalculateShadow(shadowCoord);
#endif
float3 color = albedo * max(0, dot(mainLight.direction, normalWS)) * shadowAtten;

 

然后对需要的材质进行material.EnableKeyword("SHADOW_ON")material.DisableKeyword("SHADOW_ON")开关关键字,或者用Shader.EnableKeyword("SHADOW_ON")对全场景包含这一keyword的物体进行设置
  上述情况是开关的设置,还有设置配置的情况,例如说我希望高配光照计算用PBR基于物理的光照计算方式,而低配用Blinn-Phong,其他计算例如阴影、雾效完全一致,也可以将光照计算用变体的方式分隔。

如果是shader编写的新手,可能有两个问题:
①我不能直接传递个变量到shader里,用if实时判断吗?
答:不可以,简单来说,由于gpu程序需要高度并行,shader中的分支判断需要将if else两个分支都走一遍,假如你的两个需求都有不短的代码,这样的开销太大且不合理。
②我不可以直接将shader复制一份出来改吗?
答:不是很好,例如你现在复制一份shader出来,还需要对应脚本去找到需要替换的shader然后替换。更重要的是,当你的shader同时包含很多需要切换的效果:阴影、雾效、光照计算、附加光源、溶解、反射等等,总不能有一个需求就shader*2是吧

  当你有多组关键字,阴影是否开关,是否有雾效时,你可能会写出下面这样的关键字声明:

#pragma multi_compile SHADOW_OFF SHADOW_ON
#pragma multi_compile FOG_OFF FOG_ON
#pragma multi_compile ADDLIGHT_OFF ADDLIGHT_ON
#pragma multi_compile REFLECT_OFF REFLECT_ON
//something keyword ...

 

这种写法属于比较死亡的写法,别在意,后面自然会说出各种写法中不好的地方并提出回避建议。

  而对于当前材质,就会利用上述的关键字进行排列组合,例如一个“不希望接受阴影,希望有雾,需要附加光源,不带反射”,得到的Keyword组合就是:SHADOW_OFF FOG_ON ADDLIGHT_ON REFLECT_OFF,这个Keyword组合就是一个变体。对于上面这个例子,可以得到2的4次方16个变体。

 我们知道了什么是变体,再来回答为什么要变体管理。
  可以发现上述例子中,每多一条都会乘2,实际上一列keyword声明可以不止两个,声明三个、甚至更多也是可能的。
  但不管怎么说,随着#pragma multi_compile的增加,变体数量会指数增长。这样会带来什么问题呢?
  这时候需要了解下shader到底是什么。

2. Shader

  我就当大家都知道,ShaderLab其实不是很底层的东西,它封装了图形API的Shader,以及一堆渲染命令。对于图形API,Shader是gpu的程序,不同API上传shader略有区别,例如OpenGL:

GLuint vertex_shader;
GLchar * vertex_shader_source[];//glsl源码
//创建并将源码传递给GPU
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凉亭下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值