增加镜面光泽会减少OpenGL中的光照

时间:2013-02-15 13:40:49

标签: opengl graphics lighting specular

我在更改opengl 4.3着色器中的镜面反射功率组件时遇到了问题。当我使用介于0-10之间的光泽度值时,镜面反射效果正常,但是,随着增加的值使材料更加光亮,光照强度会降低。这是我的代码:

    //Direct Lighting
vec3 L = normalize(worldPos.xyz - lightPos.xyz);
vec3 D = normalize(lightDir.xyz);
float dist = length(-L);
float I = max(dot(N.xyz, -L), 0.0);

vec3 h = normalize(-L.xyz + E);
float specLighting = 0.0;
specLighting = pow(max(dot(N.xyz, h), 0.0),50.0);

fColor.xyz = vec3(specLighting);

因此,如果将光泽值增加到50,则根本没有光照。顺便说一句,在这段代码中,我只显示镜面来调试问题。

[编辑] 对于解释中缺少细节感到抱歉,我附上了一些将镜面光泽度值从1更改为7的结果截图。正如您所看到的,当镜面高光缩小(这是我想要的)时,照明也会消退(这不是我想要的)。它达到了大约10点之后,变得完全黑了。

顺便说一下,我在像素/片段着色器中完全这样做。

我还添加了一个来自我的directx 11测试引擎的屏幕截图,使用完全相同的镜面光照代码,但光泽系数为100。

specLighting = pow(max(dot(N.xyz, h), 0.0),1.0);

specLighting = pow(max(dot(N.xyz, h), 0.0),2.0);

specLighting = pow(max(dot(N.xyz, h), 0.0),3.0);

specLighting = pow(max(dot(N.xyz, h), 0.0),5.0);

specLighting = pow(max(dot(N.xyz, h), 0.0),7.0);

directx 11 specular highlight

Directx 11:

4 个答案:

答案 0 :(得分:3)

如果要保持最小的基于光照的照明,则应添加非镜面反射镜。镜面反射分量通常用于添加高光到材质,而不是唯一的贡献者。

无论如何,你报告的变暗是增加指数的自然结果。想一想:因为向量是预规范化的,dot(N.xyz, h)不超过1.0。将0到1之间的数字提高到高功率自然会很快将结果变得非常小......这正是您想要的尖锐镜面高光!

当然,减小高光的大小会减少平均镜面反射(除非你使最大镜面反射值更亮,当然......)。但是,很少有实际对象只有 镜面反射。而且,如果一个物体 只有镜面反射,除镜面光斑外,它看起来会很暗。


另一种观察方式:您的公式为您提供镜面亮度,其最大值为1.0(这在某些方面对于传统的低动态范围计算机图形来说非常方便,其中每个颜色通道最大化1.0)。然而,在现实世界中,较亮的表面通常会使镜面反射高光变得更亮和更小,使得平均镜面反射亮度保持不变。这些情况之间的对比使情况混乱。出于实际目的,该公式是“按设计工作 - 不会修复”;通常情况下,艺术家只需调整镜面反射指数和亮度,直到获得他想要的外观。

答案 1 :(得分:0)

我最初在问题更新之前写了这个答案,并提供了足够的信息。所以在这种情况下显然不是正确的答案,但可能适用于有类似问题的人......

关于为什么镜面反射光强度会随着增加的功率而降低的一种可能的解释是,如果你是在顶点水平而不是每像素计算它。如果高光点恰好落在多边形的中间,而不是在顶点处,那么当它随着光泽度的增加而减小时,顶点贡献将快速下降,并且高光将消失。实际上对于良好的镜面反射(并且通常用于良好的光照),您需要计算每个像素,并且仅插入在多边形上实际平滑变化的事物,例如位置或法线。

答案 2 :(得分:0)

感谢所有帮助人员,

事实证明,在顶点着色器中只是一个愚蠢的错误:

而不是:

    fNorm = vec4(mat3(worldSpace)*vNorm.xyz,0);

我刚刚:

fNorm = vNorm;

答案 3 :(得分:-2)

如果你增加“光泽度”,你的材料就会变得不那么闪亮了。