通过调用glBindFramebuffer(GL_FRAMEBUFFER,0),OpenGL不会呈现到屏幕

Dom*_*ick 2 c++ opengl qt opengl-es

通常,此代码会将纹理图像渲染为屏幕.但是,如果我现在将命令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);
Run Code Online (Sandbox Code Playgroud)

想要可能出错吗?

编辑:

/*final.fsh*/

版本330核心

uniform sampler2D u_texture;
in vec4 qt_TexCoord0;

out vec4 fragColor;

void main(void)
{
    fragColor = texture(u_texture, qt_TexCoord0.xy);
}
Run Code Online (Sandbox Code Playgroud)

/*final.vsh*/

版本330核心

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);
}
Run Code Online (Sandbox Code Playgroud)

/*将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);
Run Code Online (Sandbox Code Playgroud)

Zou*_*uch 6

正如GM所述,并根据文档,glBindFramebuffer(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
Run Code Online (Sandbox Code Playgroud)

编辑:您似乎正在使用QOpenGLWidget您的OpenGL提供商/窗口系统.这些Qt家伙正在使用framebuffers来渲染他们的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
Run Code Online (Sandbox Code Playgroud)

  • 很高兴它能完成工作:)我建议你编辑你的问题,以包括你正在使用`QOpenGLWidget`的事实?它可能会帮助其他人:) (2认同)