《着色器和屏幕特效》读书笔记第七章-移动端着色器优化

本书版本为“占红来 译”版,笔记会持续更新,有错误的地方欢迎指正,谢谢!

引言

游戏制作中都会达成一个共识,就是需要优化着色器或使用更少的纹理来实现同样的效果。有了这个意识后,你在写着色器的时候,都会有意识地做一些改变。

什么是轻量着色器

着色器效率低的原因:

  1. 变量的内存消耗过大;
  2. 使用纹理数量过多。

针对第二点的解决方法大家都懂,接下来就说说第一点的解决方法:

  1. 优化变量类型,使他们在处理数据时占用更少的内存。
    比如把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. 通用的表面着色器虽然通用,但性能其实并不好。我建议采用顶点和片元着色器,因为没有光照函数,节约性能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您的第一个问题是关于Unity Shader的学习笔记,具体是在表面着色器中控制顶点变换。那么我可以回答您的问题。 在Unity中,表面着色器是一种用于控制物体表面外观的程序。它们可以控制颜色、纹理和光照等方面。而在表面着色器中,我们可以使用顶点变换来控制物体表面的外观。 顶点变换是一个将物体的顶点坐标从局部空间转换为世界空间或者相机空间的过程。在表面着色器中,我们可以通过在CG程序中编写代码来实现顶点变换。以下是一个简单的例子: ```CG // 定义变换矩阵 float4x4 worldMatrix; float4x4 viewMatrix; float4x4 projectionMatrix; // 定义输入结构体 struct appdata { float4 vertex : POSITION; }; // 定义输出结构体 struct v2f { float4 vertex : SV_POSITION; }; // 顶点变换函数 v2f vert (appdata v) { v2f o; o.vertex = mul(mul(mul(v.vertex, worldMatrix), viewMatrix), projectionMatrix); return o; } ``` 在这个例子中,我们定义了三个变换矩阵:世界矩阵、视图矩阵和投影矩阵。然后定义了一个输入结构体appdata,其中包含了顶点的位置信息。输出结构体v2f则只包含了顶点的位置信息,用于传递给像素着色器。 在vert函数中,我们首先将顶点从局部空间转换到世界空间,然后再从世界空间转换到相机空间,最后再从相机空间转换到屏幕空间。这个过程中使用了mul函数来进行矩阵乘法运算。 通过这样的方式,我们可以在表面着色器中控制顶点变换,从而实现对物体表面外观的控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值