【问题标题】:OpenGL render to cubemap using DSA (Direct State Access)OpenGL 使用 DSA(直接状态访问)渲染到立方体贴图
【发布时间】:2019-03-14 17:50:25
【问题描述】:

我尝试渲染成立方体贴图来制作动态天空盒。我尝试使用 OpenGL 4.5 的直接状态访问功能来实现它。

我想到了一个用于离屏渲染的简单 2D 纹理。

这是我的做法。我只粘贴最少且有效的代码。

// 1. Initialization code
{
    // FBO (Frame Buffer Object)
    GLuint FBO;
    glCreateFramebuffers(1, &FBO);

    // Texture2D for color buffer
    {
        GLuint colorBuffer;
        glCreateTextures(GL_TEXTURE_2D, 1, &colorBuffer);
        glTextureStorage2D(colorBuffer, 1, GL_RGB8, 1024, 1024);

        glNamedFramebufferTexture(FBO, GL_COLOR_ATTACHMENT0, colorBuffer, 0);
    }

    // RBO (Render Buffer Object) for depth buffer.
    {
        GLuint depthBuffer;
        glCreateRenderbuffers(1, &depthBuffer);
        glNamedRenderbufferStorage(depthBuffer, GL_DEPTH_COMPONENT24, 1024, 1024);

        glNamedFramebufferRenderbuffer(FBO, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
    }

    if ( glCheckNamedFramebufferStatus(m_identifier, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE )
        exit(1);
}





// 2. Drawing code
{
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO);

    glClearNamedFramebufferfv(FBO, GL_COLOR, 0, m_clearColor.data());
    glClearNamedFramebufferfv(FBO, GL_DEPTH, 0, &m_clearDepth);

    // Draw stuffs ...

    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}

所以,要渲染到立方体贴图,我的想法是用“GL_TEXTURE_CUBEMAP”替换“GL_TEXTURE_2D”。我知道我需要继续使用 glTextureStorage2D() 来创建存储。

然后,我不知道 RBO 是否会处理立方体贴图渲染...我想为每个面重用它。

最后,我完全迷失了渲染部分。至少,我知道我必须用不同的摄像机角度渲染 6 次场景才能完成立方体。但我不知道如何告诉 OpenGL 我实际渲染的是哪张脸。

我的第一个线索是使用“glNamedFramebufferDrawBuffer(FBO, GL_COLOR_ATTACHMENT0 + face)”,但它不起作用。

我在使用 glNamedFramebufferTextureLayer() 创建帧缓冲区时看到了另一种解决方案,但我不确定它是否正确。

我在网上寻找解决方案,但我找到了很多方法,有些方法与 DSA 不兼容。

有没有人做到这一点?我只需要主要思想。

【问题讨论】:

  • 尚不清楚这与 DSA 究竟有什么关系。在我看来,无论您如何创建或访问这些对象,您通常都不确定如何渲染到立方体贴图。更具体地说,不清楚您想要如何渲染到立方体贴图的面。
  • DSA 的问题是调用函数时有些不同,有些完全不同。所以我想我可能走错路了。
  • "DSA 的问题是在调用函数时存在一些差异,有些是完全不同的。" 我不记得任何例子中的 DSA 函数形式为 @987654322 @ 的行为与非 DSA gl<NonDSAPrefix><Name> 不同。在某些情况下,没有等效的 DSA(但在这些情况下,您确实不应该从一开始就使用该功能)。

标签: c opengl rendering


【解决方案1】:

你有两个选择:

使用渲染缓冲区进行多次传递

您无法创建立方体贴图渲染缓冲区。因此,如果您将渲染缓冲区用于深度缓冲区,那么您必须进行六次渲染通道,每个面一个。要将纹理的每个面依次附加到颜色缓冲区,请使用glNamedFramebufferTextureLayer

// 1. Initialization code
    // ...
    {
        GLuint colorBuffer;
        glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &colorBuffer);
        glTextureStorage2D(colorBuffer, 1, GL_SRGB8_ALPHA8, 1024, 1024);
    }

// 2. Drawing code
{
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO);

    for(int cube_map_face = 0; cube_map_face < 6; ++cube_map_face)
    {
        glNamedFramebufferTextureLayer(FBO, GL_COLOR_ATTACHMENT0, colorBuffer, 0, cube_map_face);
        glClearNamedFramebufferfv(FBO, GL_COLOR, 0, m_clearColor.data());
        glClearNamedFramebufferfv(FBO, GL_DEPTH, 0, &m_clearDepth);

        // Draw cub_map_face
    }
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}

使用几何着色器的一个通道

或者,您可以使用带有几何着色器的深度纹理立方体贴图将图元分配到每个(相关)面。

// 1. Initialization code
{
    // FBO (Frame Buffer Object)
    GLuint FBO;
    glCreateFramebuffers(1, &FBO);

    // Texture for color buffer
    {
        GLuint colorBuffer;
        glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &colorBuffer);
        glTextureStorage2D(colorBuffer, 1, GL_SRGB8_ALPHA8, 1024, 1024);
        glNamedFramebufferTexture(FBO, GL_COLOR_ATTACHMENT0, colorBuffer, 0);
    }

    // Texture for depth buffer.
    {
        GLuint depthBuffer;
        glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &depthBuffer);
        glTextureStorage2D(depthBuffer, 1, GL_DEPTH24_STENCIL8, 1024, 1024);
        glNamedFramebufferTexture(FBO, GL_DEPTH_ATTACHMENT, depthBuffer, 0);
    }

    if ( glCheckNamedFramebufferStatus(m_identifier, GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE )
        exit(1);
}  

// 2. Drawing code
{
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO);

    glClearNamedFramebufferfv(FBO, GL_COLOR, 0, m_clearColor.data());
    glClearNamedFramebufferfv(FBO, GL_DEPTH, 0, &m_clearDepth);

    // Draw stuffs ... (one pass)

    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}

您需要附加一个几何着色器来复制每个面的图元。 See here.

【讨论】:

  • 在您的第一个示例中,您每次渲染时都重新附加 RBO。那是对的吗 ?无论如何,我更喜欢第二种方式,我会用你给我的链接挖掘更多信息,谢谢。
  • @SébastienBémelmans:不,我只重新附加纹理层。您用于深度缓冲区的 RBO 仅附加一次。
  • 是的,我看错了代码。顺便说一句,我用你的第一个例子的 glNamedFramebufferTextureLayer() 完成了工作!谢谢
  • 第一个例子。如果我没有输入glNamedFramebufferTexture,FBO 将无法完成。
  • @iaomw:已经有一个glNamedFramebufferTextureLayer
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-02
  • 2017-02-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多