0

我正在尝试使用 GLSL 3.3 实现 Phong 反射模型。我已经按照教程进行了操作,尽管我已经更改了代码以匹配教程的内容,但我仍然无法创建效果。我有一个奇怪的聚光灯效果,从原点到光源所在的地方,而不是任何 Phong 反射。这是顶点着色器:

#version 330
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
out vec3 Color;
out vec3 NormalCamSpace;
out vec3 EyeDir;
out vec3 PositionWorldSpace;
out vec3 LightDirCamSpace;
uniform mat4 MVP;
uniform mat4 M;
uniform mat4 V;
uniform vec3 lightPos;

void main() {
    NormalCamSpace =(V*M *vec4(normal,0.0)).xyz;
    PositionWorldSpace = (M * vec4(position,1.0)).xyz;
    vec3 PositionCamSpace = (V*M*vec4(position, 1.0)).xyz;
    EyeDir = -PositionCamSpace;
    LightDirCamSpace = (V*vec4(lightPos, 1.0)).xyz + EyeDir;
    Color = vec3(0.0, 1.0, 1.0);
    gl_Position = MVP * vec4(position, 1.0 );
}

这是碎片着色器:

#version 330
in vec3 Color;
in vec3 NormalCamSpace;
in vec3 PositionWorldSpace;
in vec3 EyeDir;
in vec3 LightDirCamSpace;
uniform vec3 lightPos;
uniform float ambientIntensity;

out vec3 outColor;

void main() {
    vec3 n = normalize(NormalCamSpace);
    vec3 l = normalize (LightDirCamSpace);
    float cosTheta = clamp(dot(n, l),0,1);

    vec3 E = normalize(EyeDir);
    vec3 R = reflect(-l, n);
    float cosAlpha = clamp(dot(E, R),0,1);
    cosAlpha = pow(cosAlpha, 5);
    float attenIntensity = 1.0 + 0.01*distance(lightPos, PositionWorldSpace)*distance(lightPos, PositionWorldSpace);
    outColor = Color*cosTheta /attenIntensity+
    Color* vec3(0.3, 0.3, 0.3) * cosAlpha/attenIntensity+
    vec3(0.8, 0.8, 0.8) * ambientIntensity;
}

lightPos 在世界空间中。

这是相关的教程。除了镜面光照外,一切正常。

4

2 回答 2

1

我认为你的着色器很好。唯一缺少的是dot(n, l)>0计算镜面反射项时的检查,但这并不重要。问题可能是你的法线是错误的。

这是我在使用你的着色器时得到的。我将漫反射颜色设置为红色,将镜面反射颜色设置为绿色,在镜面反射高光处加起来为黄色。在我看来还不错。

在此处输入图像描述

我还想指出这LightDirCamSpace = (V*vec4(lightPos, 1.0)).xyz + EyeDir;是正确的。但我认为这样写LightDirCamSpace = (V*vec4(lightPos, 1.0)).xyz - PositionCamSpace;更清楚。

顺便说一句,而不是distance(lightPos, PositionWorldSpace)*distance(lightPos, PositionWorldSpace)你应该使用

vec3 lightVec = lightPos - PositionWorldSpace;
float attenIntensity = 1.0 + 0.01 * dot(lightVec, lightVec);

此外,视图空间中的照明很好,无需在世界空间中进行。

于 2013-07-14T10:52:34.550 回答
0

您应该使用法线和光方向向量的世界空间,而不是视图空间。可以将其视为比较 3D 空间中的两个向量,无论您从何处查看,法线和光线方向都不会改变。

编辑:另一个问题

    LightDirCamSpace = (V*vec4(lightPos, 1.0)).xyz + EyeDir;

光照方向应该是光照位置减去顶点位置(从顶点到光照的向量),同样在世界空间中。应该

    LightDirCamSpace = lightPos - PositionWorldSpace;

更正:忽略这一点,您可以在视图空间或世界空间中计算照明,对于错误信息,请查看其他答案。

于 2013-07-12T18:35:57.470 回答