我一直在基于Unity的标准BRDF编写一些自定义着色器,该着色器使用GGX分布项和Smith可见性项。在平滑度标尺的任一端(下图中的1和2)看起来都很棒。但是,将平滑度设置为大约50%时,情况开始变得有些难看(3)。增加金属性会使其变得更糟(4),并且由于不同的颜色通道以不同的速率吹出(5),强烈着色的镜面反射还会变得更糟。



是由于镜面反射项在亮点周围返回> 1造成的,可能是由于Unity破解将镜面反射镜与pi相乘(而不是除以漫反射),如下面的代码片段所示。

// Specular term
// HACK: theoretically we should divide diffuseTerm by Pi and not multiply specularTerm!
// BUT 1) that will make shader look significantly darker than Legacy ones
// and 2) on engine side "Non-important" lights have to be divided by Pi too in cases when they are injected into ambient SH
half roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
half V = SmithJointGGXVisibilityTerm (nl, nv, roughness);
half D = GGXTerm (nh, roughness);
half specularTerm = V*D * UNITY_PI; // Torrance-Sparrow model, Fresnel is applied later


HDR渲染有很大帮助,但不幸的是,我们的项目是在移动设备上使用LDR。我正在制作具有透明涂层的汽车油漆着色器,因此在很多情况下,底漆可能是半粗糙和半金属的,这似乎是此BRDF的最坏情况。谁能建议一种获得更清晰的镜面反射高光的方法?对于超出范围的镜面反射值进行某种衰减,或者完全使用不同的BRDF?

评论

您是否可以只替换修复了hack的“标准”着色器的副本?

他们似乎将BRDF乘以pi,以保持与使用Blinn-Phong及其现有球谐系统的着色器的向后兼容性。经过更多的研究,我不确定这是问题所在,正如Stefan在下面说的那样,实际上,高光会比散射光要亮得多,而LDR却没有带宽。在Google图像上查看具有各种材质值的GGX渲染时,这似乎已经超出了统一性。

#1 楼

仅当整个管道都是针对物理单位构建时,才使用基于物理的BRDF才有意义-如果没有某种形式的色调映射,则无法正确显示极端的值范围。您没有包括代码的那部分,但是从它的外观来看,我想说的是您正在做一个简单的clip(),然后进行linear-> sRGB转换,这会导致高亮显示。

由于您还没有准备好在HDR中运行整个框架,因此可以将诸如S形运算符之类的简单操作应用于镜面反射组件。与其他BRDF相比,这可能看起来有点不足,但应该使这些亮点更加令人愉悦。

评论


$ \ begingroup $
的确如此。将HDR颜色转换为LDR的简单运算符是简化的reinhard运算符,它是:colorOut = colorIn /(colorIn + 1.0)。这不是最好的,但是很容易。它使颜色无论数量多少都永远不会达到1.0。有关更多信息,请查看以下内容:imdoingitwrong.wordpress.com/2010/08/19/…
$ \ endgroup $
–艾伦·沃尔夫(Alan Wolfe)
17年7月22日在0:34

$ \ begingroup $
谢谢大家的建议。我猜我需要的是像音频处理中使用的软膝盖压缩器一样的东西-线性低于阈值,并且在其之上具有强烈的像reinhard一样的衰减。虽然不确定数学上是什么样的函数。我要在周末玩耍,看看我能想到什么。
$ \ endgroup $
– russ
17年7月22日在7:16