Opengl 渲染到立方体贴图

Opengl 渲染到立方体贴图,opengl,glsl,fbo,Opengl,Glsl,Fbo,根据,可以使用几何体着色器和附加到帧缓冲区对象的立方体贴图在立方体贴图的6个面上渲染场景。我想用这种方法创建一个阴影贴图。然而,似乎有一个我无法解决的冲突: 我只能将具有GL_DEPTH_组件作为内部类型的纹理附加到GL_DEPTH_附件_EXT 深度纹理只能是1D或2D 如果要附加立方体贴图,所有其他附加的纹理也必须是立方体贴图 所以,当我想渲染到立方体贴图时,看起来我不能使用任何深度测试。或者我到底错过了什么 编辑:新的Nvidia驱动程序(180.48)似乎支持深度立方体贴图。好的,在这里

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

  • 我只能将具有GL_DEPTH_组件作为内部类型的纹理附加到GL_DEPTH_附件_EXT
  • 深度纹理只能是1D或2D
  • 如果要附加立方体贴图,所有其他附加的纹理也必须是立方体贴图
  • 所以,当我想渲染到立方体贴图时,看起来我不能使用任何深度测试。或者我到底错过了什么


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

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

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

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

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

    //深度立方体映射
    glGenTextures(1和tDepthCubeMap);
    glBindTexture(GL_纹理_立方体_贴图,tDepthCubeMap);
    glTexParameterf(GL_纹理\立方体\贴图,GL_纹理\最小\过滤器,GL_线性);
    glTexParameterf(GL_纹理、立方体、贴图、GL_纹理、MAG_过滤器、GL_线性);
    glTexParameterf(GL_纹理、立方体贴图、GL_纹理、包裹、GL_夹紧到边);
    glTexParameterf(GL_纹理、立方体贴图、GL_纹理、包裹、GL_夹紧到边);
    glTexParameterf(GL_纹理、立方体贴图、GL_纹理、包裹、GL_夹紧到边);
    用于(uint面=0;面<6;面++){
    glTexImage2D(GL_纹理_立方体_贴图_正X+面,0,GL_深度_组件24,
    宽度、高度、0、总图深度分量、总图浮动、空);
    }
    //彩色立方体贴图
    glGenTextures(1,&t彩色立方贴图);
    glBindTexture(GL_纹理_立方体_贴图,tColorCubeMap);
    glTexParameterf(GL_纹理\立方体\贴图,GL_纹理\最小\过滤器,GL_线性);
    glTexParameterf(GL_纹理、立方体、贴图、GL_纹理、MAG_过滤器、GL_线性);
    glTexParameterf(GL_纹理、立方体贴图、GL_纹理、包裹、GL_夹紧到边);
    glTexParameterf(GL_纹理、立方体贴图、GL_纹理、包裹、GL_夹紧到边);
    glTexParameterf(GL_纹理、立方体贴图、GL_纹理、包裹、GL_夹紧到边);
    用于(uint面=0;面<6;面++){
    GLTEXAGE2D(GL_纹理_立方体_贴图_正X+面,0,GL_RGBA,
    宽度、高度、0、GL_RGBA、GL_浮点、空);
    }
    //帧缓冲区对象
    glGenFramebuffersEXT(1和fbo);
    glBindFramebufferEXT(GLU帧缓冲区EXT,fbo);
    glFramebufferTextureARB(GL_帧缓冲区_扩展,GL_深度_附件_扩展,tDepthCubeMap,0);
    glFramebufferTextureARB(GL_帧缓冲区_扩展,GL_颜色_附件0_扩展,tColorCubeMap,0);
    glDrawBuffer(GL\u颜色\u附件0\u外部);
    如果(!isValidFBO()){
    glDeleteFramebuffersEXT(1,&fbo);
    fbo=0;
    }
    
    • 如果只想拥有深度贴图,则必须更改glDrawBuffer(GL\u COLOR\u ATTACHMENT0\u EXT);到glDrawBuffer(GL_NONE);在验证之前(以及绘制之前)
    • MIN和MAG过滤器必须设置为有效值(默认值为GL\u NEAREST\u MIPMAP\u LINEAR)
    • 所有纹理的宽度和高度必须相同
    要渲染到立方体贴图的面,需要使用几何体着色器。下面的着色器忽略了一些旋转,但应该清楚它的作用。gl_层用于将基本体定向到正确的面(0=+X,1=-X,…)

    #版本120
    #扩展GL\U EXT\U几何图形\U着色器4:启用
    真空总管(真空){
    inti,层;
    用于(层=0;层<6;层++){
    gl_层=层;
    对于(i=0;i<3;i++){
    gl_位置=gl_位置在[i];
    发射顶点();
    }
    EndPrimitive();
    }
    }
    
    我不确定渲染到立方体贴图与几何体着色器有什么关系,它感觉完全独立,但我没有答案。几何体着色器可以为每个输入三角形创建6个输出三角形,并将其重定向到每个立方体贴图面(请参见“分层渲染”)。如果没有着色器,我必须附加每个面并渲染几何体6次。我想知道,你能粘贴用立方体纹理创建帧缓冲区的代码吗?我自己对此很感兴趣。为什么不为立方体的每一面使用6个单独的帧缓冲区呢?如何从着色器内部绑定立方体贴图的不同侧面?您知道什么扩展可以使用GL_纹理\立方体\贴图\正的\ X和GL_深度\组件24调用glTexImage2D吗?GL_EXT_depth_纹理明确禁止这样做。我需要知道我可以检查哪些GL扩展,以知道我是否可以使用此功能。我在标准扩展注册表中没有看到一个。谢谢。这是我最初的问题。似乎没有任何地方特别提到这是允许的(但这可能已经改变了,我没有再次检查)。您可能可以检查ARB_geometry_shader4,然后查看设置FBO是否不会产生错误。我尝试将其与核心opengl 3.3一起使用,但失败了。我从立方体地图上读到的只是噪音。如果你能提供一个有效的例子,那将是非常好的。我在我的引擎中使用它,它似乎适用于GTX 970和更高版本,但是当我试图在GTX 880上使用它时,我得到了一个黑色的结果,当试图在英特尔上使用它时,它只是崩溃了。
    // 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;
    }
    
    #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();
        }
    }