GLSL高光照明

12
当我使用我的着色器时,我得到以下结果: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);
}

[编辑2] 正如Joakim所指出的,我没有在片段着色器中对varEyeNormal进行归一化处理。修复后,片段着色器中的结果要好得多。我还在uEyePos上使用了normalize函数,因此镜面反射不再变暗。感谢所有的帮助。

enter image description here


我认为你应该否定你的法线。(在暗面上的亮点) - Aki Suihkonen
使用这个代码,我完全看不到高光反射。vec3 negNormal = vec3(-attrNorm.x, -attrNorm.y, -attrNorm.z); vec3 N = uN * negNormal; - SMGhost
我在谈论第二张图片,如果镜面反射也是正的话,漫反射光应该是正的。你能把它做成一个jsfiddle吗? - Aki Suihkonen
1个回答

19
简短回答:您需要在片段着色器中对varEyeNormal进行归一化处理,而不是在顶点着色器中进行。

详细回答:为了获得平滑的光照效果,您需要按像素而不是按顶点计算法线。在顶点着色器中计算的varyings会在传递到片段着色器之前进行线性插值,这在某些情况下很有效,但在其他情况下则效果较差。

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

为了纠正这个问题,您需要在片段着色器中对法线进行归一化处理,而不是在顶点着色器中进行。

标准矩阵应为模型视图矩阵的转置的逆的上3x3部分,如果模型视图仅包含旋转和平移(没有缩放),则等同于模型视图矩阵的上3x3部分。

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

(根据下面的评论进行了更正。)

5
你有关于正常矩阵的观点是错误的。它是模型视图矩阵的上部 3x3 矩阵的逆转置。因此,如果模型视图矩阵只包含旋转和平移,它与模型视图矩阵的上部 3x3 矩阵完全相同(因为旋转的逆转置会被抵消,平移无论如何都被忽略),这可能就是为什么反转-转置对 OP 也没有任何区别的原因。 - Christian Rau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接