我正在通过opengl.org中的以下Phong Illumination着色器阅读:
Phong Illumination in 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之间的点积的结果不正确,因为它们的坐标不相同。我是对的吗?
答案 0 :(得分:4)
因此,我们不能简单地从v中减去光位置来计算 L向量,因为它们不在同一坐标系中。 此外,L和N之间的点积的结果将是不正确的 因为他们的坐标不一样。我是对的吗?
没有
gl_LightSource[0].position.xyz
不您设置GL_POSITION
的值。 GL会在GL_MODELVIEW
调用时自动将位置乘以当前glLight()
矩阵。照明计算完全在固定功能GL的眼睛空间中完成。因此,V
和N
必须转换为眼睛空间,gl_LightSource[].position
已经转换为眼睛空间,因此代码是正确的,实际上并没有混合不同的坐标空间。
您使用的代码依赖于已弃用的功能,使用了GL的许多旧的固定功能功能,包括该特定问题。在现代GL中,那些内置的制服和属性不存在,你必须定义自己的 - 你可以随意解释它们。
你当然也可以忽略那个约定,并且仍然使用不同的坐标空间进行内置的光照计算,并且在设置位置时通过简单地选择其他矩阵来解释gl_LightSource[].position
(通常,光的世界)空间位置设置,而GL_MODELVIEW
矩阵仅包含视图变换,因此某些世界固定光源的眼睛空间光位置出现,但您可以做任何您喜欢的事情)。但是,所提供的代码意味着可以作为固定功能管道的一些“插入式”替换,因此它将以与固定功能管道相同的方式解释这些内置的制服和属性。