当我使用我的着色器时,我得到以下结果:


一个问题是镜面光是变形的,你可以看到球形三角形,另一个是,我可以看到镜面反射,我不应该(第二张图像).一个spehere光在顶点着色器中完成,另一个在片段中完成.
以下是我的顶点灯光着色器的样子:Vertex:
// 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;
}
Run Code Online (Sandbox Code Playgroud)
分段:
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;
}
Run Code Online (Sandbox Code Playgroud)
我提供的代码数据可能是错误的.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;
}
Run Code Online (Sandbox Code Playgroud)
片段着色器文件:
// 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);
}
Run Code Online (Sandbox Code Playgroud)
[EDIT2]正如Joakim指出的那样,我没有在片段着色器中对varEyeNormal进行规范化.修复后,片段着色器的结果要好得多.我还在uEyePos上使用了normalize函数,因此镜面反射不再是黑暗的一面.谢谢你的帮助.

Joa*_*ård 19
简短回答:您需要varEyeNormal在片段着色器中进行标准化,而不是在顶点着色器中进行标准化.
更长的答案:为了获得平滑的光照,您需要计算每个像素的法线而不是每个顶点.在顶点着色器中计算的变量在传递给片段着色器之前进行线性插值,在某些情况下,这种方法很有用,但在其他情况下则更差.
您看到三角形边缘的原因是因为法线之间的插值导致顶点之间的所有像素中的法线短于1.0法线.
要纠正此问题,您需要在片段着色器中而不是在顶点着色器中规范化法线.
Normal矩阵应该是Modelview矩阵的逆转置的上3x3,如果Modelview只包含旋转和平移(没有缩放),它相当于Modelview矩阵的上3x3
有关Normal矩阵的更多信息,请参阅:http://www.lighthouse3d.com/tutorials/glsl-tutorial/the-normal-matrix/
(根据下面的评论编辑正确性.)