【问题标题】:Rendering to cube map渲染到立方体贴图
【发布时间】:2010-10-02 12:58:05
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我不确定渲染到立方体贴图与几何着色器有什么关系,感觉完全独立,但我没有答案。
  • 几何着色器可以为每个输入三角形创建 6 个输出三角形,并将其重定向到每个立方体贴图面(参见“分层渲染”)。如果没有着色器,我必须附加每个面并渲染几何体 6 次。
  • 我想知道,你能粘贴使用立方体纹理创建帧缓冲区的代码吗?我自己对此很感兴趣。
  • 为什么不对立方体的每一边使用 6 个单独的帧缓冲区呢?您如何从着色器内部绑定立方体贴图的不同面?

标签: opengl glsl fbo


【解决方案1】:

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

当然可以使用 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();
    }
}

【讨论】:

  • 你知道什么扩展可以用 GL_TEXTURE_CUBE_MAP_POSITIVE_X 和 GL_DEPTH_COMPONENT24 调用 glTexImage2D 吗? GL_EXT_depth_texture 明确禁止这样做。我需要知道我可以检查哪些 GL 扩展才能知道我是否可以使用此功能。我没有在标准扩展注册表中看到一个。谢谢。
  • 那是我最初的问题。似乎没有任何地方特别提到它是允许的(虽然可能已经改变,我没有再次检查)。您可能可以检查 ARB_geometry_shader4,然后查看设置 FBO 是否不会产生错误。
  • 我尝试让它与核心 opengl 3.3 一起使用,但失败了。从立方体贴图读取时,我得到的只是噪音。如果您能提供一个工作示例,那就太好了。
  • 我在我的引擎中使用它,它似乎适用于 GTX 970 及更高版本,但是当尝试在 GTX 880 上使用它时,我得到一个黑色的结果,当尝试使用它时英特尔它只是崩溃了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多