Unity Shader渲染时需要注意的几点

        第一点就是之前也提到过的渲染平台的差异,OpenGL和DirectX的屏幕空间坐标的差异,虽然大多数情况下,这样的差异并不会造成影响,因为Unity在背后为我们处理了这些问题,但是当我们开启了抗锯齿(Edit>Project Setting>Quality>Anti Aliasing)并且在此时使用了渲染到纹理技术。

        此时Unity首先渲染得到屏幕图像,再由硬件进行抗锯齿处理后,得到一张渲染纹理给我们进行后续处理,当我们只需要处理一张渲染图像时,也不需要处理翻转的问题,但是如果我们需要同时处理多张渲染图像且开启了抗锯齿,就需要在顶点着色器中翻转某些渲染纹理的纵坐标。

//判断是否是DirectX类型的平台
#if UNITY_UV_STARTS_AT_TOP
//判断是否开启了抗锯齿
if(_MainTex_TexelSize.y<0)
    nv.y = 1-uv.y;
#endif

        shader的语法差异,如果看到以下的报错信息,都是因为DirectX9/11对Shader的语义更加严格造成的。 

        float4 v = float4(0.0);

        就比如这行代码,在OpenGL平台上是合法的,它会得到一个4个分量都是0.0的float4类型的变量,但是在directX 11平台上,我们必须提供和变量类型相匹配的参数数目。

        float4 v = float4(0.0,0.0,0.0,0.0);

        这行报错信息,往往出现在表面着色器中,表面着色器的顶点函数有一个使用了out修饰符的参数,但它没有对这个参数的所有成员变量都进行初始化。


        然后就是之前提到过的shader语义差异,在不同平台上对POSITION和SV_POSITION的等价判断是不同的。


        最后给出一些如何规范Shader代码的建议。

        三种精度的数值类型,但给的范围并不是绝对正确的,尤其是在不同平台和GPU上,在PC上比较难看出精度带来的不同,但是在移动平台的GPU上的确会有不同的精度范围,且运算速度也会有所差异,因此我们应该确保在真正的移动平台上验证我们的Shader。

        fixed精度实际上只在一些比较旧的移动平台上有用,在大多数现代的GPU上,他们内部把fixed和half当成同等精度来对待。

        尽管有以上的不同,但是一个基本建议就是尽可能使用精度较低的类型,因为可以优化Shader的性能,特别是在移动平台上,我们可以使用fixed类型来储存颜色和单位矢量,如果要存储更大范围的数据可以选择half类型,最差的情况下在选择使用float。 

        错误提示:

         出现如上错误提示大多是因为在Shader中进行了过多的运算,使得需要的临时寄存器数目或指令数目超过了当前可支持的数目。通常我们可以通过制定更高级的Shader Target来消除这些错误。

        在编写Shader的时候,要对分支、循环语句的流程控制语句小心使用,如果使用了大量的流程控制语句,可能会使得Shader性能成倍下降 。

        一个解决办法是尽量吧计算向流水线上端移动,比如片元着色器中的计算放到顶点着色器,或者直接在CPU中进行预计算,再把结果传递给Shader,如果不可避免需要使用分支语句来运算时,有如下建议:

        1.分支判断语句中使用的条件变量最好是常数,即在Shader运行过程中不会发生变化

        2.每个分支中包含的操作指令数尽可能少

        3.分支的嵌套层数尽可能少

        不要除以0.

        虽然不一定会造成崩溃,但是得到的结果也是不确定的。

        解决办法是对于除数可能为0的情况,强制截取到非0范围。 

猜你喜欢

转载自blog.csdn.net/weixin_45081191/article/details/129207732