问题起因
最近我有一位朋友研究Colin的Screen Space Decal时,对其中的一个部分表示非常不解:
1 | //in vertex shader : |
他很想知道为什么i.viewRayOS /= i.viewRayOS.w
这一步不能在vertex shader中做,如果改在vertex中做就会出错。
如果在Vertex Shader中除去w值,则会与期望情况产生误差,在此我将误差可视化
1 | //in vertex shader : |
结果如图:
可见当frag在顶点位置时计算结果是一致的,但越远离顶点,误差可能越大。
诶,那我如果不是除w,而是除以一个定值呢?
1 | //in vertex shader : |
嗯,没有误差。
那么,为什么除以w不行,而除以一个定值就没问题呢?
透视校正插值
一个值从顶点着色器到片元着色器之间经历了什么?没错,就是光栅化,而光栅化会让一个值经过透视校正插值
具体可参考此文:https://zhuanlan.zhihu.com/p/144331875
直接使用三角形屏幕空间坐标进行重心坐标插值会出现错误
很显然,这个变换是非线性的,那么先做除法还是后做除法会导致结果不一样……但这样解释大概还是有些难懂。
那么我们将计算简化后,自己代入值计算看看:
假设X,Y是向量值,ZA,ZB为两个顶点的深度,w则与代码中含义相同。
左边为在frag中进行除法获得的值,而右边则是在vertex中进行除法获得的值,
很显然两个值并不会相等。
而为什么接近顶点时误差会小也很好解释,
当片元相当接近顶点,则α、β、γ中有一个值为极为接近1,其余两个值则接近0,此时不等式两边会长得极为相似(但只有特殊情况是真正相等,其余情况只是相差较小),读者不妨自己算算看。
而除以一个定值为什么无所谓,也相当好理解了:
这怎么想都是相等的。
感谢您阅读完本文,若您认为本文对您有所帮助,可以将其分享给其他人;若您发现文章对您的利益产生侵害,请联系作者进行删除。