1. ホーム
  2. c++

[解決済み] glBindFramebuffer(GL_FRAMEBUFFER,0) を呼び出すと、OpenGL が画面にレンダリングしない。

2022-02-12 10:44:48

質問

通常、このコードはテクスチャの画像をスクリーンにレンダリングします。しかし、今、このコードに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);

何が間違っているのだろうか?

EDIT

/* 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);

解決方法は?

G.M.が述べているように、また、それによると ドキュメント , 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

EDIT あなたが使っているのは QOpenGLWidgetOpenGL プロバイダ/ウィンドウシステムです。その Qt の人はフレームバッファを使ってUIをレンダリングしているので、その結果のコンテンツは、あなたの QOpenGLWidget はFBOの中に描画されます。

つまり、(少なくとも私の経験では、この問題に取り組むより良い方法があるかもしれません)バックバッファでレンダリングすることはもうできない、ということです。 Qt s 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