0

我在互联网http://rioki.org/2013/03/07/glsl-skybox.html上找到了这个用于立方体贴图环境纹理的代码(实际上是渲染天空盒)。但我不明白它为什么起作用。

void main()
{
    mat4 r = gl_ModelViewMatrix;
    r[3][0] = 0.0;
    r[3][1] = 0.0;
    r[3][2] = 0.0;

    vec4 v = inverse(r) * inverse(gl_ProjectionMatrix) * gl_Vertex;

    gl_TexCoord[0] = v; 
    gl_Position    = gl_Vertex;
} 

在世界坐标中也是如此gl_Vertex,但是通过将其乘以投影矩阵的倒数,然后再乘以模型视图矩阵,我们会得到什么?

这是我用来绘制天空盒的代码

void SkyBoxDraw(void)
{
GLfloat SkyRad = 1.0f;

glUseProgramObjectARB(glsl_program_skybox);
glDepthMask(0);
glDisable(GL_DEPTH_TEST);
// Cull backs of polygons
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
glEnable(GL_TEXTURE_CUBE_MAP);

glBegin(GL_QUADS);
    //////////////////////////////////////////////
    // Negative X
    glTexCoord3f(-1.0f, -1.0f, 1.0f);
    glVertex3f(-SkyRad, -SkyRad, SkyRad);

    glTexCoord3f(-1.0f, -1.0f, -1.0f);
    glVertex3f(-SkyRad, -SkyRad, -SkyRad);

    glTexCoord3f(-1.0f, 1.0f, -1.0f);
    glVertex3f(-SkyRad, SkyRad, -SkyRad);

    glTexCoord3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(-SkyRad, SkyRad, SkyRad);
    ......
    ......
glEnd();

glDepthMask(1);
glDisable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_CUBE_MAP);

glUseProgramObjectARB(0);

}
4

1 回答 1

2

所以 gl_Vertex 在世界坐标中......

不不不,gl_Vertex在对象/模型空间中,除非我在其他地方看到一些代码(例如,您的顶点位置是如何在程序的实际非着色器部分中计算的),否则:) 在 OpenGL 中,我们从对象空间跳到当我们乘以组合的模型*视图矩阵时,眼睛/视图/相机空间。如您所见,相同的坐标空间有很多名称,但对象空间绝对不是世界空间的同义词。将 r3 设置为 < 0, 0, 0, 1 > 基本上会在不影响方向的情况下重新定位相机的原点,这在您只想知道立方体贴图查找的方向时很有用。

也就是说,简而言之,使用立方体贴图时您想要什么。只是一个简单的方向向量。采用 3D 矢量而不是 4D的事实textureCube (...)直接暗示它正在寻找方向而不是位置。位置向量有第四个分量,方向没有。因此,从技术上讲,如果您想将此着色器移植到现代 OpenGL,您可能会使用 an out vec3and swizzle .xyzoff of v,因为这v.w是不必要的。

...但是我们将其乘以投影矩阵的倒数然后乘以模型视图矩阵会得到什么?

当您乘以这些矩阵的逆时,您基本上是在撤消投影。这个着色器有意义的唯一方法是,如果您为顶点传递的坐标是在剪辑空间中定义的。因此,与其从对象空间通过 GL 管道并最终在屏幕空间中结束,您想要相反的情况,只是因为您的着色器中不涉及视口,我们无法处理屏幕空间。关于如何计算顶点位置的更多信息应该可以解决这个问题。

于 2013-10-09T21:15:40.493 回答