【问题标题】:GLSL specular lightingGLSL 镜面光照
【发布时间】:2012-10-28 15:18:02
【问题描述】:

当我使用我的着色器时,我得到以下结果:

一个问题是镜面光有点变形,你可以看到球体三角形,另一个问题是,我可以看到我不应该看到的镜面光(第二张图片)。一个球光在顶点着色器中完成,另一个在片段中完成。

这是我的顶点光照着色器的样子: 顶点:

// Material data.
uniform vec3 uAmbient;
uniform vec3 uDiffuse;
uniform vec3 uSpecular;
uniform float uSpecIntensity;
uniform float uTransparency;

uniform mat4 uWVP;
uniform mat3 uN;
uniform vec3 uSunPos;
uniform vec3 uEyePos;
attribute vec4 attrPos;
attribute vec3 attrNorm;
varying vec4 varColor;

void main(void)
{
    vec3 N = uN * attrNorm;
    vec3 L = normalize(uSunPos);
    vec3 H = normalize(L + uEyePos);
    float df = max(0.0, dot(N, L));
    float sf = max(0.0, dot(N, H));
    sf = pow(sf, uSpecIntensity);

    vec3 col = uAmbient + uDiffuse * df + uSpecular * sf;
    varColor = vec4(col, uTransparency);
    gl_Position = uWVP * attrPos;
}

片段:

varying vec4 varColor;

void main(void)
{

    //vec4 col = texture2D(texture_0, varTexCoords);
    //col.r += uLightDir.x;
    //col.rgb = vec3(pow(gl_FragCoord.z, 64));
    gl_FragColor = varColor;

}

我从代码中提供的数据有可能是错误的。 uN 是世界矩阵(不是倒置也不是转置,即使这样做似乎没有什么不同)。 UWVP - 世界观投影矩阵。

任何关于问题可能出在哪里的想法都将不胜感激。

[编辑] 这是我在片段中完成的光照计算: 顶点着色器文件:

uniform mat4 uWVP;
uniform mat3 uN;
attribute vec4 attrPos;
attribute vec3 attrNorm;
varying vec3 varEyeNormal;

void main(void)
{
    varEyeNormal = uN * attrNorm;
    gl_Position = uWVP * attrPos;
}

片段着色器文件:

// Material data.
uniform vec3 uAmbient;
uniform vec3 uDiffuse;
uniform vec3 uSpecular;
uniform float uSpecIntensity;
uniform float uTransparency;

uniform vec3 uSunPos;
uniform vec3 uEyePos;
varying vec3 varEyeNormal;

void main(void)
{
    vec3 N = varEyeNormal;
    vec3 L = normalize(uSunPos);
    vec3 H = normalize(L + uEyePos);

    float df = max(0.0, dot(N, L));
    float sf = max(0.0, dot(N, H));
    sf = pow(sf, uSpecIntensity);

    vec3 col = uAmbient + uDiffuse * df + uSpecular * sf;

    gl_FragColor = vec4(col, uTransparency);
}

[EDIT2] 正如 Joakim 指出的那样,我没有在片段着色器中规范化 varEyeNormal。修复后,片段着色器的结果要好得多。我还在 uEyePos 上使用了 normalize 功能,因此镜面反射不再出现暗面。感谢大家的帮助。

【问题讨论】:

  • 我相信你应该否定你的法线。 (黑暗面的亮点)
  • 像这样:vec3 negNormal = vec3(-attrNorm.x, -attrNorm.y, -attrNorm.z); vec3 N = uN * negNormal; ?有了这个,我根本看不到镜面反射。
  • 我说的是第二张图片,如果镜面反射也是正的,漫射光应该是正的。你能用这个做一个jsfiddle吗?

标签: c++ opengl glsl


【解决方案1】:

简答:您需要在片段着色器中规范化varEyeNormal,而不是在顶点着色器中。

更长的答案: 为了获得平滑的光照,您需要计算每个像素而不是每个顶点的法线。在顶点着色器中计算的变化在传递给片段着色器之前被线性插值,这在某些情况下作为快捷方式非常有效,但在其他情况下更糟糕。

您看到三角形边缘的原因是法线之间的插值导致顶点之间所有像素的法线短于 1.0。

要纠正这个问题,您需要在片段着色器而不是顶点着色器中标准化法线。

Normal 矩阵应该是 Modelview 矩阵的逆转置的上 3x3,如果 Modelview 仅包含旋转和平移(无缩放),则相当于 Modelview 矩阵的上 3x3

有关 Normal 矩阵的更多信息,请参阅:http://www.lighthouse3d.com/tutorials/glsl-tutorial/the-normal-matrix/

(根据下面的评论编辑正确性。)

【讨论】:

  • 你关于法线矩阵的观点是错误的。它是模型视图矩阵的上 3x3 的逆 转置。因此,如果模型视图矩阵只有旋转和平移,它与模型视图矩阵的上 3x3 完全相同(因为反转和转置抵消了旋转,并且平移无论如何都是 ingored),这可能就是它没有的原因对 OP 是否反转转置它没有任何影响。
猜你喜欢
  • 1970-01-01
  • 2011-12-27
  • 2015-01-31
  • 2020-07-24
  • 2015-08-29
  • 2021-04-09
  • 2021-08-05
  • 2011-08-31
  • 2012-04-04
相关资源
最近更新 更多