GLSL镜面反射照明

时间:2012-11-08 12:09:55

标签: c++ opengl glsl

当我使用着色器时,我得到以下结果: enter image description here

enter image description here

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

以下是我的顶点灯光着色器的样子: 顶点:

// 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函数,因此镜面反射不再是黑暗的一面。感谢您的帮助。

enter image description here

1 个答案:

答案 0 :(得分:19)

简短回答:您需要在片段着色器中标准化varEyeNormal,而不是在顶点着色器中标准化。

更长的回答: 为了获得平滑的光照,您需要计算每个像素的法线而不是每个顶点。在顶点着色器中计算的变量在传递给片段着色器之前进行线性插值,在某些情况下,它在某些情况下很有用,但在其他情况下更差。

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

要纠正此问题,您需要在片段着色器中而不是在顶点着色器中规范化法线。

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

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

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