shader中使用模型坐标参与计算,就得注意批处理的影响,比如在场景中某个材质的物体出现一个的时候,表现正常,但是一旦再出现第二个,两个物体的表现就变成玄学了(不是自己预期的那样),一旦由隐藏掉另外一个,剩下的另一个由正常了。当然这肯定不是玄学,得分析分析其中的原因。
做一个简单的测试,使一个正方体上半部分显示绿色,下半部分显示红色:
shader中在fragment中通过模型坐标Y的大小来决定颜色是红是绿:
fixed4 frag (v2f i) : SV_Target
{
if(i.modelPos.y < 0){
return fixed4(1,0,0,1);
}
else{
return fixed4(0,1,0,1);
}
}
此时拷贝一个同样的立方体,尝试修改position,神奇的事情发生了:
不是代码已经说好了,只是上面一部分是绿色下面是红色吗,怎么这个全绿了,额,这只是异常表现的一种情况,那么简单的几行代码,颜色值一定没有错是红与绿(没有鲤鱼和驴),那么问题一定处在了if判断那里,就是 i.modelPos.y不是我们想的那样(内置立方体y的坐标是-0.5与0.5)。
打开FrameDebug可以清楚的看到,原来两个正方体已经被进行了动态合批处理DynamicBatch原本一个立方体24个顶点,而在渲染过程中将两个立方体网格合成了一个大的网格48个顶点。那么既然网格已经进行了合并,新网格上顶点的模型坐标也就不再是之前的模型坐标了,所以在执行之前的代码逻辑得到的结果就大概率不是预期结果。
解决办法:
1.在设置中关闭Unity的动态合批(如果没有开启这个选项,那么也就不会遇到这样的情况了)
在PlayerSettings中能找到一个DynamicBatching的选项,取消掉勾选即可
不过虽然能解决当前这个问题,但是想到DynamicBatching能省下不少DrawCall,而且还是自动进行!所以不推荐这个做法。
2.正解:在Shader中添加tag关闭当前材质的动态合批属性
"DisableBatching" = "true"
Tags
{
"RenderType"="Opaque"
"DisableBatching" = "true" //这里记得加上这个标记
}
添加上这个Tag后,结果正确了