12

当我使用我的着色器时,我得到以下结果: 在此处输入图像描述

在此处输入图像描述

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

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

// 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 功能,因此镜面反射不再出现暗面。感谢所有的帮助。

在此处输入图像描述

4

1 回答 1

19

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

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

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

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

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

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

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

于 2012-11-08T12:32:27.567 回答