GLSL PBS 实现,奇怪的着色器行为
Posted
技术标签:
【中文标题】GLSL PBS 实现,奇怪的着色器行为【英文标题】:GLSL PBS implementation, weird shader behaviour 【发布时间】:2015-08-18 09:40:53 【问题描述】:我正在使用 Cook-Torrance 镜面反射 BRDF + Disney 的漫反射 BRDF 光模型,如果单独应用,它们可以正常工作。不幸的是,如果我尝试将它们结合起来,就会发生一些奇怪的事情: 漫反射光照贴图如下所示: 镜面光照贴图(注意地形边缘的伪影):
生成的光照贴图是这样计算的:
float result = Fr + Fd;
其中 Fd 是漫反射 BRDF 组件,Fr 是镜面反射 BRDF 组件。
为什么它会在生成的光照贴图上出现这样的伪影?
我在想产生的光强度超出范围 [0;1],检查我是否修改了代码如下:
return result <= 1.0 ? result : 1.0;
生成的光照贴图:
如您所见,现在所有伪影的强度都为 1.0(它们显然超出 [0;1] 范围),但如果高光贴图包含零,为什么还会出现这种情况?
完整的着色器代码:Pastebin
【问题讨论】:
似乎很难解释。只有一次我从着色器中看到过这样的奇怪结果,它是由一些未定义的数学引起的,这些数学导致 NaN 以奇怪的方式传播和破坏东西。也许看看所有的 pow 函数,并确保第一个参数不能为负数,方法是临时修改 abs/max/saturate 或所有这些函数(线 pow( pow(dotNH, 2.0) * (m_alpha - 1.0) + 1.0 , 2.0));例如可能有负数)。如果没有得到它,我会尝试简化 @Columbo 谢谢。 N和L的点积为0,除以零误差。我添加了 abs 函数作为修补程序。 【参考方案1】:正如@Columbo 提到的,这是 NaN 异常(引发除以零的原因),这导致了奇怪的着色器行为。我稍微修改了代码:
float F_Schlick (in float f0, in float f90, in float u)
return f0 + ( f90 - f0 ) * pow(clamp(1.0 - u, 0.0, 1.0), 5.0); //line 34
点积应该大于零:
float dotNV = abs(dot(N, V));
float dotNL = abs(dot(N, L));
The final shader code
【讨论】:
以上是关于GLSL PBS 实现,奇怪的着色器行为的主要内容,如果未能解决你的问题,请参考以下文章
带有 Blinn-Phong GLSL 着色器、点光源的奇怪结果