我正在阅读下面的Phong照明着色器,它在opengl.org中有:
顶点和碎片着色器如下:
顶点着色器:
varying vec3 N;
varying vec3 v;
void main(void)
{
v = vec3(gl_ModelViewMatrix * gl_Vertex);
N = normalize(gl_NormalMatrix * gl_Normal);
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}碎片着色器:
varying vec3 N;
varying vec3 v;
void main (void)
{
vec3 L = normalize(gl_LightSource[0].position.xyz - v);
vec3 E = normalize(-v); // we are in Eye Coordinates, so EyePos is (0,0,0)
vec3 R = normalize(-reflect(L,N));
//calculate Ambient Term:
vec4 Iamb = gl_FrontLightProduct[0].ambient;
//calculate Diffuse Term:
vec4 Idiff = gl_FrontLightProduct[0].diffuse * max(dot(N,L), 0.0);
Idiff = clamp(Idiff, 0.0, 1.0);
// calculate Specular Term:
vec4 Ispec = gl_FrontLightProduct[0].specular
* pow(max(dot(R,E),0.0),0.3*gl_FrontMaterial.shininess);
Ispec = clamp(Ispec, 0.0, 1.0);
// write Total Color:
gl_FragColor = gl_FrontLightModelProduct.sceneColor + Iamb + Idiff + Ispec;
}我想知道他是如何计算观看者向量或v的。因为通过将顶点位置与gl_ModelViewMatrix相乘,结果将出现在视图矩阵中(与世界坐标相比,视图坐标大部分时间是旋转的)。
因此,我们不能简单地从v中减去光的位置来计算L矢量,因为它们不在同一坐标系中。而且,L和N之间的点积的结果是不正确的,因为它们的坐标是不一样的。我说得对吗?
发布于 2015-01-17 15:51:25
因此,我们不能简单地从v中减去光的位置来计算L矢量,因为它们不在同一坐标系中。而且,L和N之间的点积的结果是不正确的,因为它们的坐标是不一样的。我说得对吗?
不是的。
gl_LightSource[0].position.xyz不是您将GL_POSITION设置为的值。在调用GL_MODELVIEW时,GL将自动将位置乘以当前的glLight()矩阵。照明计算完全在眼睛空间,在固定功能GL.因此,V和N都必须转换成眼睛空间,而gl_LightSource[].position已经被转换成眼睛空间,所以代码是正确的,实际上没有混合不同的坐标空间。
您使用的代码依赖于不推荐的功能,使用GL的许多旧的固定函数功能,包括这个特定的问题。在现代GL中,这些内置的制服和属性并不存在,您必须定义自己的制服和属性--您可以根据自己的喜好来解释它们。
当然,您也可以忽略这个约定,仍然使用不同的坐标空间来计算内置的照明,并通过在设置位置时选择其他矩阵来解释gl_LightSource[].position (通常,光的世界空间位置是设置的,而GL_MODELVIEW矩阵只包含视图转换,以便某些世界静止光源的眼睛空间光位置出现,但是你可以做任何你喜欢的事情)。然而,所提供的代码将作为固定功能管道的“插入”替代,因此它将以固定功能管道的方式来解释这些内置的制服和属性。
https://stackoverflow.com/questions/28000883
复制相似问题