有一个场景包含一些物体和地形。当我尝试旋转对象时,法线保持不变。意味着物体的暗侧保持物体的暗侧。 我的镜面闪电正在发挥作用。
顶点着色器:
uniform vec3 lightPos;
uniform sampler2D Texture;
varying vec2 TexCoord;
varying vec3 position;
varying vec3 vertex;
varying mat3 nMat;
varying mat3 vMatrix;
varying vec3 normal;
varying vec3 oneNormal;
varying vec3 lightPos2;
void main()
{
gl_Position=gl_ModelViewProjectionMatrix*gl_Vertex;
position=vec3(gl_ModelViewMatrix*gl_Vertex);
vMatrix = mat3(gl_ModelViewMatrix);
lightPos2 = vec3(gl_ModelViewMatrix*vec4(lightPos,1.0));
vertex = vec3(gl_Vertex);
nMat = gl_NormalMatrix;
normal=gl_NormalMatrix*gl_Normal;
oneNormal = gl_Normal;
TexCoord=gl_MultiTexCoord0.xy;
}
Fragment Shader:
varying vec3 position;
varying vec3 normal;
uniform sampler2D Texture;
varying vec2 TexCoord;
uniform vec3 lightPos;
varying vec3 vertex;
uniform vec3 lambient;
uniform vec3 ldiffuse;
uniform vec3 lspecular;
uniform float shininess;
varying mat3 nMat;
varying mat3 vMatrix;
varying vec3 oneNormal;
varying vec3 lightPos2;
void main()
{
float dist=length(vertex-lightPos);
float att=1.0/(1.0+0.1*dist+0.01*dist*dist);
vec4 TexColor = texture2D(Texture, TexCoord);
vec3 ambient=TexColor.rgb*lambient; //the ambient light
//=== Diffuse ===//
vec3 surf2light=normalize(position-lightPos2);
float dcont=max(0.0,
dot( normalize(nMat*(-normal)), nMat*surf2light) );
vec3 diffuse=dcont*(TexColor.rgb*ldiffuse);
//=== Specular ===//
vec3 surf2view = normalize(lightPos-position);
surf2light=nMat*normalize(-vertex);
vec3 reflection=reflect(-surf2view,normalize(normal));
float scont=pow(max(0.0,dot(surf2light,reflection)),shininess);
vec3 specular=scont*lspecular;
gl_FragColor=vec4((ambient+diffuse+specular)*att,1.0);
}
答案 0 :(得分:0)
你正在改变法线。但至少对于部分光照计算,您使用的光源位置也会转换为相同的坐标空间。如果同时转换法线和光源,法线相对于光源的方向将再次相同。
从顶点着色器中提取关键线:
position=vec3(gl_ModelViewMatrix*gl_Vertex);
lightPos2 = vec3(gl_ModelViewMatrix*vec4(lightPos,1.0));
normal=gl_NormalMatrix*gl_Normal;
gl_NormalMatrix
对应gl_ModelViewMatrix
,对变换方向向量而不是点进行必要的调整。因此,模型视图转换已应用于position
,lightPos2
和normal
的所有内容。
然后,所有这三个值(应用插值)都会传递到片段着色器中,您可以在此处计算漫反射照明术语:
vec3 surf2light=normalize(position-lightPos2);
float dcont=max(0.0,
dot( normalize(nMat*(-normal)), nMat*surf2light) );
vec3 diffuse=dcont*(TexColor.rgb*ldiffuse);
现在,这里有几个问题:
nMat
(正常矩阵)应用于两个向量,即使它们已经被转换。它没有坏处,因为如果对两个向量应用相同的旋转,点积不会改变,但它没有意义。position
,lightPos2
,normal
)都由模型视图矩阵转换。所以他们的相对位置/方向与他们原来的完全相同。计算结果与将其应用于相应的未转换向量时的结果相同。您需要决定要用于照明计算的坐标系。至少有几种选择。最简单的一个可能是使用眼睛坐标空间。要执行此操作,您可以在将视图转换传递到着色器之前将其应用于灯光位置,然后在着色器代码中直接使用此灯光位置,而无需任何其他转换。
由于您说镜面反射照明工作正常,并且您在那里使用制服lightPos
,因此可能就像在漫反射计算中使用该变量而不是lightPos2
一样简单