本书版本为“占红来 译”版,笔记会持续更新,有错误的地方欢迎指正,谢谢!
引言
游戏制作中都会达成一个共识,就是需要优化着色器或使用更少的纹理来实现同样的效果。有了这个意识后,你在写着色器的时候,都会有意识地做一些改变。
什么是轻量着色器
着色器效率低的原因:
- 变量的内存消耗过大;
- 使用纹理数量过多。
针对第二点的解决方法大家都懂,接下来就说说第一点的解决方法:
- 优化变量类型,使他们在处理数据时占用更少的内存。
比如把float都改成half或fixed。
struct Input
{
float2 uv_MainTex;
};
//把float2改为half2
inline float4 LightingSimpleLambert (SurfaceOutput s, float3 lightDir, floatatten){}
改为:
inline fixed4 LightingSimpleLambert (SurfaceOutput s, fixed3 lightDir, fixed atten){}
2.充分利用Unity内置光照模型变量来控制光照在着色器中的处理过程以减小内存开销。
#pragma surface surf SimpleLambert exclude_path:prepass noforwardadd
exclude_path:prepass告诉Unity只开启某些特定的渲染工作,即排除了延迟的光照Pass,这意味着:如果使用延迟渲染的prepass的光照函数,着色器不会使用之,而是寻找默认的光照函数;noforwardadd告诉Unity此Shader对象只接受一个单一的平行光光源作为逐像素处理光源,因而只计算其他所有光源的顶点光照来节省对每个像素的操作。这样可以极大地减少光照的数量。
3.通过法线贴图和漫反射纹理共享UV来进一步优化。
surf()函数中:o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_NormalMap));
uv_NormalMap修改为uv_MainTex。如此,我们已经对法线贴图没有需求了,便可删除Input结构中的法线贴图的UV。
我们用最小的数据达到了同样的效果~但如果优化着色器一直是一个模棱两可的问题,要性能还是要画面得根据实际情况选择。
对着色器进行性能分析
那如何找到着色器性能损失的问题所在,Unity为我们内置的性能分析器,能使我们逐帧看到GPU、CPU、渲染、内存、音效、联网等对象的每一个部件的使用情况。
通过Window|Profiler或Ctrl+7打开性能分析器。
具体用法需要自己去体会,实践出真知!加油~
移动平台上的着色器修改
只需在着色器编写的时候做一些简单的调整就可以使它在移动平台上运行得更快~
调整包括上面提及的,还可以有:
1.
#pragma surface surf MobileBlinnPhong exclude_path:prepass nolightmap noforwardadd halfasview
nolightmap:告诉Unity此着色器不支持Unity自带的贴图系统提供的光照贴图;
halfasview:告诉Unity别用viewDir,而用半角向量作为视线方向计算高光,就是BlinnPhong光照模型的原理。
2. 复杂的数学函数(如 pow,exp,log,cos,sin,tan 等等)会大大增加 GPU 负担,所以一个好的经验法则是,此类运算在每个像素中不得超过一个。考虑在合适时使用查找纹理作为替代选择。
3. 通用的表面着色器虽然通用,但性能其实并不好。我建议采用顶点和片元着色器,因为没有光照函数,节约性能。