一、Debug
最讨厌康熙的第8个儿子。
三种Untiy Shader的调试方法:
1.使用假彩色图像
假彩色图像是指用假彩色技术生成的一种图像(照片为真彩色图像),一张假彩色图像可以用来可视化一些数据。
主要思想就是把需要调试的变量映射到[0,1]之间,输出到屏幕上,通过屏幕上的像素颜色判断值是否正确。
可见112页详细介绍。
2.使用 Visual Studio
vs中提供了对Unity Shader的调试功能----Graphics Debugger。
通过Graphics Debugger,我们不仅可以查看像素颜色、位置信息,还可以对顶点着色器和片元着色器进行单步调试。
3.帧调试器
Unity官方针对渲染的调试器。
位置:Window–>Frame Debugger
具体介绍可见114页。
二、渲染平台差异
1.坐标差异
OpenGL 与 DirectX 水平相同,竖直方向上相反。
屏幕空间坐标 DX(0,0) 在左上角,OpenGL在左下角。
大多数情况不会有影响,在我们使用渲染到纹理技术时,如果不采取措施,可能导致纹理翻转,但这种情况通常Unity会帮助我们处理。
但如果我们开启了抗锯齿操作时(Edit->Project Setting->Quality->Anti Aliasing),并在此时我们使用到了渲染纹理技术,这时我们得到的屏幕图像并不会被Unity翻转(DX下),如果此时我们此时屏幕特效只需要处理一张渲染图象,我们仍然不需要在意纹理的翻转问题(Graphics.Blit调用时Unity会帮我们进行处理),但如果我们此时需要处理多张渲染图象时(同样开启抗锯齿),例如同时处理屏幕图像和法线纹理,这时这些图像可能就是朝向不同(只在DX平台上存在这种情况)。
此时,我们需要自己在顶点着色器中进行纵坐标翻转:
#if UNITY_UV_STARTS_AT_TOP //判断是否在DX平台
if (_MainTex_TexelSize.y<0) //判断是否开启了抗锯齿(开启抗锯齿主纹理纹素坐标竖直方向会变成负数)
uv.y=1-uv.y; //纵坐标转换
#endif
具体判断使用时机见116页中间段举例。
三、Shader语法差异
1.OpenGL可以float4(0.0),定义4个分量都是0的float,DX不可以。
2.
void ver(inout appdata_full v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input ,o); //需要对所有参数进行初始化
}
3.tex2D 函数 , DX不可以使用,可以使用tex2Dlod(#pragma target 3.0)代替。
4.尽量使用通用语句:SV_POSITION、SV_Target等等。
四、Shader 整洁
1.float、half、fixed
上述精度并不一定(不同平台、不同GPU可能不同),
PC上常常采用最高的来计算,所以PC上很难看出差别。移动平台可能会有差异。
fixed实际上只在旧平台上使用。
使用建议:
尽量使用精度低的,提高Shader性能(尤其是移动平台)
fixed用来存储颜色和单位矢量,更大的数据再依次选择half、float。
2.DX平台会更严格
3.避免不必要的计算
Shader Model是微软的一套规范,决定Shader中各个特性的能力。
等级越高,能力越大。
如果提示一些计算过多、寄存器不够、指令过多,可以使用更高等级的Shader Model来消除错误。
具体Shader Model等级差别 见118页。
4.慎用分支、循环
GPU不同于CPU,CPU中最基本的东西却是GPU中最浪费时间性能的。
分支循环会降低GPU的并行处理操作。
建议:
(1.如果有这样的大量的流程控制语句,那我们尽量将计算向流水线上端移动,片元着色器–>顶点着色器–>CPU,再把结果传递给Shader。
(2. 分支判断语句中使用的条件变量最好是常数。
(3. 每个分支的操作指令数尽可能少。
(4. 分支的嵌套层数尽可能少。
5.不要除以0
除0不会Shader崩溃,但是会造成很多麻烦,(平台、效果、问题等等)
我们可以判断是否为0,也可以用一个特别小的数代替0 (0.000001)。