代码之家  ›  专栏  ›  技术社区  ›  Maurice Gilden

渲染到立方体贴图

  •  12
  • Maurice Gilden  · 技术社区  · 17 年前

    根据 ARB_geometry_shader4 可以使用几何着色器将场景渲染到立方体贴图的6个面上,并将立方体贴图附加到帧缓冲区对象。我想用这种方式创建阴影贴图。然而,似乎有一个我无法解决的冲突:

    1. 我只能将内部类型为GL_DEPTH_COMPENT的纹理附加到GL_DEPTH_ ATTACHMENT_EXT。
    2. 深度纹理只能是1D或2D。
    3. 如果我想附加立方体贴图,所有其他附加的纹理也必须是立方体贴图。

    因此,当我想渲染到立方体贴图时,我似乎无法使用任何深度测试。或者我到底错过了什么?

    编辑: 看起来新的Nvidia驱动程序(180.48)支持深度立方体贴图。

    1 回复  |  直到 17 年前
        1
  •  12
  •   Maurice Gilden    17 年前

    好的,在这里回答一些其他问题:

    当然,可以使用6个FBO,每个人脸一个。或者使用一个FBO并在绘制之前附着每个面。在这两种情况下,立方体贴图面都将被视为任何其他2D纹理,您可以将其与普通2D纹理或渲染缓冲区一起使用。所有可能的方式(如果硬件支持的话)可能没有太大区别。

    然而,也可以一步画出所有东西,因为我很好奇这是如何做到的,所以我做了一些研究。

    为了创建一个将立方体贴图的所有面附着到单个附着点的FBO,我使用了以下代码(用D编写):

    // depth cube map
    glGenTextures(1, &tDepthCubeMap);
    glBindTexture(GL_TEXTURE_CUBE_MAP, tDepthCubeMap);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    for (uint face = 0; face < 6; face++) {
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_DEPTH_COMPONENT24,
            width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, null);
    }
    
    // color cube map
    glGenTextures(1, &tColorCubeMap);
    glBindTexture(GL_TEXTURE_CUBE_MAP, tColorCubeMap);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    for (uint face = 0; face < 6; face++) {
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA,
            width, height, 0, GL_RGBA, GL_FLOAT, null);
    }
    
    // framebuffer object
    glGenFramebuffersEXT(1, &fbo);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
    glFramebufferTextureARB(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, tDepthCubeMap, 0);
    glFramebufferTextureARB(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, tColorCubeMap, 0);
    
    glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
    
    if (!isValidFBO()) {
        glDeleteFramebuffersEXT(1, &fbo);
        fbo = 0;
    }
    
    • 如果你只想有一个深度图,你必须改变 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glDrawBuffer(GL_NONE); 在验证之前(以及在绘制之前)
    • MIN和MAG过滤器必须设置为有效值(默认值为GL_NEAREST_MIPMAP_LINEAR)
    • 所有纹理的宽度和高度必须相同

    要渲染到立方体贴图的面,您需要一个几何着色器。以下着色器缺少一些旋转,但应该清楚它的作用。gl_Layer用于将图元引导到正确的面(0=+X,1=-X,…)。

    #version 120
    #extension GL_EXT_geometry_shader4 : enable
    
    void main(void) {
        int i, layer;
        for (layer = 0; layer < 6; layer++) {
            gl_Layer = layer;
            for (i = 0; i < 3; i++) {
                gl_Position = gl_PositionIn[i];
                EmitVertex();
            }
            EndPrimitive();
        }
    }
    
    推荐文章