我正在尝试使用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在世界空间。
这是tutorial,如果它是相关的。除了高光照明外,一切都有效。
答案 0 :(得分: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);
此外,lighting in view space is fine, there's no need to do it in world space.
答案 1 :(得分:0)
您应该使用法线和光线方向矢量的世界空间,而不是视图空间。可以把它想象为比较3D空间中的两个向量,无论你在哪里观看,法线和光线方向都不会改变。
编辑:另一个问题
LightDirCamSpace = (V*vec4(lightPos, 1.0)).xyz + EyeDir;
光线方向应该是光线位置减去顶点位置(从顶点到光线的矢量),再次在世界空间中。应该是
LightDirCamSpace = lightPos - PositionWorldSpace;
更正:忽略这一点,您可以在视图空间或世界空间中计算光照,对于错误信息感到抱歉,请查看其他答案。