【问题标题】:OpenGL does not render to screen by calling glBindFramebuffer(GL_FRAMEBUFFER,0)OpenGL 不会通过调用 glBindFramebuffer(GL_FRAMEBUFFER,0) 渲染到屏幕
【发布时间】:2017-02-25 12:14:24
【问题描述】:

通常,此代码会将纹理图像渲染到屏幕上。但是,如果我现在将命令 glBindFramebuffer(GL_FRAMEBUFFER,0) 添加到代码中,它将不会呈现任何内容。它以 glClearColor 的颜色渲染屏幕。我正在使用 QT,所以使用 QOpenGLWidget。

glViewport(0, 0, _width, _height);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

glClearColor(0.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);

_program.bind();
glBindVertexArray(_vao);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureID);
glUniform1i(glGetUniformLocation(_program.programId(), "u_texture"), 1);

glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);

想可能会出错吗?

编辑:

/* final.fsh */

# version 330 core

uniform sampler2D u_texture;
in vec4 qt_TexCoord0;

out vec4 fragColor;

void main(void)
{
    fragColor = texture(u_texture, qt_TexCoord0.xy);
}

/* final.vsh */

# version 330 core

layout (location = 0) in vec3 a_position;

out vec4 qt_TexCoord0;

void main(void)
{
    gl_Position =  vec4(a_position, 1.0);

    const mat4 B = mat4(0.5,  0.0, 0.0, 0.0,
                            0.0,  0.5, 0.0, 0.0,
                            0.0,  0.0, 0.5, 0.0,
                            0.5,  0.5, 0.5, 1.0);

    qt_TexCoord0 = B * vec4(a_position, 1.0);
}

/* 将 VAO 加载到 GPU */

GLfloat max_ = 1.0;
GLfloat min_ = -1.0;
GLfloat vert[] = {
    max_,  max_, 0,
    max_, min_, 0,
    min_, max_, 0,

    max_,  min_, 0,
    min_, min_, 0,
    min_,  max_, 0,
};

glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);

GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);

glBufferData(GL_ARRAY_BUFFER, sizeof(vert), vert, GL_STATIC_DRAW);

glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*3, (GLvoid*)0);
glBindVertexArray(0);

【问题讨论】:

  • 0 为目标调用glBindFramebufferbreak any existing binding to GL_FRAMEBUFFER。鉴于这种情况,您为什么要调用它并不明显。目的是什么?
  • 这个想法是将来对帧缓冲区进行一些额外的渲染调用。然后将结果传递给该代码以在屏幕上呈现结果。
  • glDrawBuffer(GL_BACK) 我猜应该可以解决问题
  • 嗯,不知道这有什么帮助。这应该放在哪里?我没有绑定任何帧缓冲区。

标签: c++ qt opengl


【解决方案1】:

正如 G.M. 所说,根据the docsglBindFramebuffer(GL_FRAMEBUFFER, 0)“破坏了帧缓冲区对象与目标的现有绑定”。在使用帧缓冲区进行一些离屏渲染后,您需要此调用。当您想最终渲染到屏幕上时,您必须通过调用glDrawBuffer(GL_BACK) 来渲染后台缓冲区

所以你的渲染循环可能看起来像

// Do some rendering stuff in n offscreen textures
glBindFramebuffer(GL_FRAMEBUFFER, the_buffer);
glDrawBuffers(n, buffers);
// Rendering calls

// Finally use the results for the final rendering 
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawBuffer(GL_BACK);
// Rendering calls

编辑: 看来您正在使用 QOpenGLWidget 作为您的 OpenGL 提供程序/窗口系统。 Qt 的人正在使用帧缓冲区来呈现他们的 UI,而您的 QOpenGLWidget 的结果内容是在 FBO 中绘制的。

所以,这意味着(至少根据我的经验,可能有更好的方法来解决这个问题),是你不能再在后台缓冲区中渲染,你必须在Qts framebuffer 中渲染。

执行此操作的一种方法(同样,它可能根本不是最好的方法,但它对我有用)是在渲染开始时保存绑定的帧缓冲区,并在此缓冲区中进行最终渲染.这导致

// First of all, save the already bound framebuffer
GLint qt_buffer;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &qt_buffer);

// Do some rendering stuff in n offscreen textures
glBindFramebuffer(GL_FRAMEBUFFER, your_buffer);
glDrawBuffers(n, buffers);
// Rendering calls

// Finally use the results for the final rendering 
if (glIsFramebuffer(qt_buffer))
{
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glDrawBuffer(GL_BACK);
}
else
{
    glBindFramebuffer(GL_FRAMEBUFFER, qt_buffer);
    glDrawBuffers(1, buffers);
}
// Rendering calls

【讨论】:

  • 好的,为了测试,我把我的代码加倍了。并将 glBindFramebuffer 更改为成功创建的 FBO。与:GLuint 附件 [2] = {GL_COLOR_ATTACHMENT0,GL_COLOR_ATTACHMENT1}; glDrawBuffers(2, 附件);其余的就像你展示的那样,通过使用 glDrawBuffer 再次将 0 绑定到 Framebuffer。但什么都没有改变
  • 等等,你用的是Qt的QOpenGLWidget吗?
  • 是的,有区别吗?
  • 哦,是的。那行得通^^我实际上使用GL_FRAMEBUFFER_BINDING 来获取FBO。但我在初始化 OpenGL 后调用它,它告诉我它是 0 ^^。但是是的,我不得不将它移到paintGL()。谢谢
  • 很高兴它完成了这项工作:) 我可以建议您编辑您的问题以包括您使用QOpenGLWidget 的事实吗?它可能会帮助其他人:)
【解决方案2】:

我有同样的问题,最后我发现原因是glBindFramebuffer(GL_FRAMEBUFFER, 0); QOpenGLWidget的默认framebuffer可能不是0,需要通过调用QOpenGLContext::defaultFramebufferObject()来获取

所以改成这样:

glViewport(0, 0, _width, _height);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject()); //<-- change here

glClearColor(0.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);

_program.bind();
glBindVertexArray(_vao);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureID);
glUniform1i(glGetUniformLocation(_program.programId(), "u_texture"), 1);

glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-18
    • 1970-01-01
    • 2015-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多