GLSL - 从世界坐标计算屏幕坐标不正确

3
我刚实现了nVidia的GPU Gems 3书中的“神光”着色器:作为后期处理的体积光散射。总的来说,除了一个缺陷外,它几乎是完美的。不知何故,灯光的位置没有随着场景的变化而移动。下面是图片示例:第一张图片看起来完全正常;然而第二张图片并非如此,从白色球体应该向外辐射光线,但是看起来位置没有从第一张图片改变。在顶点着色器中进行转换:
uniform vec4 light_coords;
varying vec2 light_pos;

void main()
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_TexCoord[0] = gl_MultiTexCoord0;
    light_pos = vec2(gl_ModelViewProjectionMatrix * light_coords) * 0.5 + 0.5;
}

这个正确吗?

光的位置在世界坐标系中是(0, 0, -2)。代码里可能还有其他错误,但在深入研究之前,我想确保我的顶点着色器计算是正确的。

编辑:根据Nicol Bolas的建议,我做了一些更改,效果好了一些,但仍然不正确。

当摄像机处于原始位置时,它看起来仍然很好,但当我旋转场景时,计算出来的光位置似乎现在太靠左了。

enter image description here

这是我正在使用的GLSL代码:

uniform vec4 light_coords;
uniform mat4 light_modelview;
varying vec2 light_pos;

void main()
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_TexCoord[0] = gl_MultiTexCoord0;
    light_pos = vec2(gl_ProjectionMatrix * light_modelview * light_coords) * 0.5 + 0.5;
}

在这里获取 light_modelview
glPushMatrix()
glTranslatef(self.position[0], self.position[1], self.position[2])
glScalef(2, 2, 2)       
self.modelview = glGetFloatv(GL_MODELVIEW_MATRIX)
glCallList(self.sphere) 
glLightfv(self.light_id, GL_POSITION, self.position)
glPopMatrix()

position[0, 0, -2]。它被传递到着色器中作为light_coords

理想情况下,如果light_pos在屏幕上,我希望它可以在(0, 0)到(1, 1)的任何位置,如果它不在屏幕上,则大于或小于该范围。

你有什么线索吗?我对OpenGL还比较陌生,所以我有点不确定哪个是做什么的。

1个回答

4
如果light_coords是在世界坐标系中,那么将其乘以gl_ModelViewProjectionMatrix只有在gl_Vertex也在世界坐标系中时才有意义。但我怀疑它是否在世界坐标系中。
一般来说,你不会把光线方向或者light_coords传递到世界坐标系中。你应该传递到视图坐标系中。你需要在CPU上从世界坐标系转换到视图坐标系,并将视图坐标系的坐标放入着色器中。

嗯,有没有一种有效的方法来进行这种转换?我正在使用OpenGL的Python绑定,所以我希望尽可能多地保留在着色器或某些OpenGL调用中。 - Dane Larsen
1
@DaneLarsen:每帧只需要执行一次。我相信你的CPU可以处理在Python中每帧执行一次单个矩阵乘法,即使是这样。我可以告诉你如何在着色器中实现它,但我担心你会选择在GPU上执行而不是将其放在CPU上并查看其对任何事情的影响很小。此外,这将需要明确使用世界空间矩阵,这在GPU上永远不是好事。 - Nicol Bolas
好的,明天我会尝试一下。谢谢你的帮助! - Dane Larsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接