了解一个Opengl着色器代码 - cubemap?

时间:2013-10-09 18:07:19

标签: opengl vertex-shader

我在互联网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);

}

1 个答案:

答案 0 :(得分:2)

  

所以gl_Vertex是世界坐标......

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

简而言之,就是使用立方体贴图时的所需内容。只是一个简单的方向向量。 textureCube (...)采用3D矢量而不是4D的事实立即提示它正在寻找方向而不是位置。位置向量具有第4个分量,方向不具有。所以,从技术上讲,如果你想将这个着色器移植到现代OpenGL,你可能会使用out vec3.xyz之间的v,因为v.w是不必要的。

  

...但是我们通过乘以投影矩阵的逆然后乘以模型视图矩阵得到什么呢?

当你乘以这些矩阵的倒数时,你基本上是撤消投影。此着色器有意义的唯一方法是,您为顶点传递的坐标是否在剪辑空间中定义。因此,不是从对象空间通过GL管道进入最后屏幕空间,而是想要反过来,只是因为视口不涉及着色器,我们无法处理屏幕空间。关于如何计算顶点位置的更多信息应该清除它。