OpenGL多重渲染目标-黑色输出 我目前正在为我的学校使用C++、SFML(OpenGL上下文创建、核心3.3)和OpenGL来绘制游戏项目。

OpenGL多重渲染目标-黑色输出 我目前正在为我的学校使用C++、SFML(OpenGL上下文创建、核心3.3)和OpenGL来绘制游戏项目。,opengl,glsl,framebuffer,Opengl,Glsl,Framebuffer,最近,我决定实现运动模糊。为此,我需要帧缓冲区对象中渲染的每个像素的运动向量。所以在我的FBO中,我有两个纹理目标: 一个用于颜色输出 一个用于运动矢量 颜色输出已正确填充,但运动矢量始终为黑色。我使用喇叭来检查我的FBO纹理的内容 我知道我的问题可能来自我的纹理创建,因为我不太了解内部纹理格式等等 以下是我的帧缓冲区创建: void Framebuffer::create(int sizeX, int sizeY, bool depthBuffer, int repeatMode) {

最近,我决定实现运动模糊。为此,我需要帧缓冲区对象中渲染的每个像素的运动向量。所以在我的FBO中,我有两个纹理目标:

  • 一个用于颜色输出
  • 一个用于运动矢量
颜色输出已正确填充,但运动矢量始终为黑色。我使用喇叭来检查我的FBO纹理的内容

我知道我的问题可能来自我的纹理创建,因为我不太了解内部纹理格式等等

以下是我的帧缓冲区创建:

void Framebuffer::create(int sizeX, int sizeY, bool depthBuffer, int repeatMode)
{
    _texture = new GLuint[2];
    std::memset(_texture, 0, sizeof(GLuint) * 2);

    // Create OpenGL framebuffer
    glGenFramebuffersEXT(1, &_fbo);
    glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, _fbo);

    // Create texture
    glGenTextures(textNbr, _texture);

    for (unsigned int i = 0; i < 2; ++i)
    {
        glBindTexture(GL_TEXTURE_2D, _texture[i]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, repeatMode);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, repeatMode);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        // Color - 4 float components
        if (i == 0)
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, sizeX, sizeY, 0, GL_RGBA, GL_FLOAT, NULL);
        // Motion vector - 2 float components
        else
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, sizeX, sizeY, 0, GL_RG, GL_FLOAT, NULL);

        // Even if I use "glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, sizeX, sizeY, 0, GL_RGBA, GL_FLOAT, NULL);" for both texture, my motion texture is black

        glBindTexture(GL_TEXTURE_2D, 0);
        // getColorAttachment only return GL_COLOR_ATTACHMENTi_EXT
        glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, getColorAttachment(i), GL_TEXTURE_2D, _texture[i], 0);
    }

    // Generate depth buffer
    if (depthBuffer == true)
    {
        glGenRenderbuffersEXT(1, &_depth);
        glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, _depth);
        glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, sizeX, sizeY);
        glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
        glFramebufferRenderbufferEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, _depth);
    }

    // Check completion
    GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
        ogl::error("Can't complete framebuffer creation");

    // Clean
    unbind();
}
结果:


在评论中,您提到启用
GL\u BLEND
会导致问题。这是意料之中的。片段着色器输出的颜色值始终为4分量RGBA向量,无论帧缓冲区采用何种格式。GL的以下阶段仍然适用于这4个组件。它们可能只是在稍后写入实际帧缓冲区时丢弃它们。如果您只是将它们声明为vec2,那么其他组件就是未定义的。在这种情况下,形式(0,0,0,1)的vec4扩展不适用(这仅在从输入属性或纹理读取时进行,因此,在这种情况下,您在注释中引用的GL文档是不相关的)。因此,混合只适用于未定义的alpha值,这也可能是由于意外而始终为0

但是,由于您只想混合真实颜色缓冲区,因此我建议您使用而不是
glEnable()
来仅为第一个绘制缓冲区启用混合


另一种选择是使用
out vec4
并明确地将1写入alpha-在这种情况下,您仍然可以使用2通道帧缓冲区。位由该缓冲区不必要的混合触发的额外帧缓冲区读取仍将是性能损失,因此我更喜欢第一个选项。

EDIT:我没有glCheckError()中的错误EDIT2:据我所知,我的运动纹理的alpha通道似乎有问题。如果禁用GL_BLEND,我可以看到我的velocity纹理:但OpenGL文档说:“GL_RG:每个元素都是红/绿双精度。GL将其转换为浮点,并通过附加0表示蓝色,附加1表示alpha将其组装为RGBA元素。每个组件都被钳制在[0,1]范围内。”关于赋值0和1的逻辑,这是OpenGL为纹理和顶点属性扩展向量的典型方式。它们被视为4D向量,缺失的分量用0,0,1赋值。如果只有2D输入向量,则该列表中的最后两个分量将使其成为4D。这允许2D/3D矢量作为齐次坐标工作,并使RGB颜色不透明,因此这是一种良好的行为。感谢您的解释。我检查了我的运动纹理中的alpha通道,它总是1,所以这是预期的工作。我不明白的是我的运动纹理和GL_混合模式之间的关系。禁用“GL_混合”时,我的运动纹理将正确填充,否则它将完全为黑色。此外,如果我在片段着色器中将运动向量输出为vec4而不是vec2(alpha值为1),则我不必禁用“GL_混合”,运动纹理也将正确填充。这真的很奇怪。这是一个非常有趣的答案。非常感谢。我只是浪费了几个小时试图了解我的着色器出了什么问题。只是禁用了GL_BLEND。我永远也猜不到。谢谢!
void Framebuffer::bind(void)
{
    glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, _fbo);

    GLuint *attachment = new GLuint[2];
    for (unsigned int i = 0; i < 2; ++i)
        attachment[i] = getColorAttachment(i);
    glDrawBuffers(2, attachment);
    delete[] attachment;
}
#version 330

in vec4 Color0;

layout(location = 0) out vec4 FragmentColor;
layout(location = 1) out vec2 MotionVector;

void main(void)
{
    FragmentColor = Color0;
    MotionVector = vec2(1);
}