首页 文章

OpenGL Qt:使用framebuffers进行bloom效果的问题

提问于
浏览
0

我正在关注这个tutorial的绽放效果 .

我正在使用 Qt 并且我正在尝试渲染的场景由五个立方体和五个随机放置的灯组成,类似这样 .

不幸的是,当我尝试使用framebuffers时,渲染的场景是完全空的(只有背景颜色) .

这些是代码的相关部分 .

initializeGL method

void initializeGL()
{
    initializeOpenGLFunctions();

    // ...

    // hdr framebuffer

    glGenFramebuffers(1, &(FBOs[0]));

    glBindFramebuffer(GL_FRAMEBUFFER, FBOs[0]);

    glGenTextures(2, &(textures[0]));

    for (int i = 0; i < 2; i++)
    {
        glBindTexture(GL_TEXTURE_2D, textures[i]);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, geometry().width(), geometry().height(), 0, GL_RGB, GL_FLOAT, NULL);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, textures[i], 0);
    }

    GLuint rbo;
    glGenRenderbuffers(1, &rbo);
    glBindRenderbuffer(GL_RENDERBUFFER, rbo);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, geometry().width(), geometry().height());
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);

    GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
    glDrawBuffers(2, attachments);

    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    {
        qDebug() << "framebuffer NOT complete";
    }

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

paintGL method

void paintGL()
{
    view.setToIdentity();
    view.lookAt(camera.eye, camera.center, camera.up);

    glClearColor(background.redF(), background.greenF(), background.blueF(), background.alphaF());
    glEnable(GL_DEPTH_TEST);

    // draw scene

    glBindFramebuffer(GL_FRAMEBUFFER, FBOs[0]);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    for (auto position : positions)
    {
        drawCube(position);
    }

    for (auto light : lights)
    {
        drawLightMarker(light);
    }

    // draw frame

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    drawQuad();

    // draw next frame
    update();
}

drawQuad method

void drawQuad()
{
    GLuint* vao = &VAOs[BLOOM];

    if (*vao == 0)
    {
        glGenVertexArrays(1, vao);

        float l = 1.0f;
        QVector2D LD(-l, -l); // left-down
        QVector2D LU(-l, +l); // left-up
        QVector2D RD(+l, -l); // right-down
        QVector2D RU(+l, +l); // right-up

        QVector<QVector2D> vertices = { LD, RD, LU, LU, RD, RU };

        QVector<QVector2D> texcoords;

        for (auto v : vertices)
        {
            texcoords += (v + QVector2D(l, l)) / (2.0f * l);
        }

        // bind vao
        glBindVertexArray(*vao);
        // vertices
        GLuint vbo;
        glGenBuffers(1, &vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(QVector2D), &(vertices[0]), GL_STATIC_DRAW);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(QVector2D), static_cast<void*>(nullptr));
        glEnableVertexAttribArray(0);
        // texcoords
        GLuint tbo;
        glGenBuffers(1, &tbo);
        glBindBuffer(GL_ARRAY_BUFFER, tbo);
        glBufferData(GL_ARRAY_BUFFER, texcoords.size()*sizeof(QVector2D), &(texcoords[0]), GL_STATIC_DRAW);
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(QVector2D), static_cast<void*>(nullptr));
        glEnableVertexAttribArray(1);
        // unbind buffer object
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        // unbind vao
        glBindVertexArray(0);
    }

    GLuint program = programs[BLOOM];
    glUseProgram(program);

    glUniform1i(glGetUniformLocation(program, "scene"), 0);
    glUniform1i(glGetUniformLocation(program, "bloom"), 1);

    glUniform1i(glGetUniformLocation(program, "effect"), true);

    glBindVertexArray(*vao);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, textures[0]);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, textures[1]);

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

cubes fragment shader

#version 450 core

layout (location = 0) out vec4 pixel;
layout (location = 1) out vec4 bloom;

struct Material
{
    // material properties
};

uniform Material material;

struct Light
{
    // light properties
};

uniform Light[5] lights;

uniform vec3 eye;

in FragData
{
    vec3 position;
    vec3 normal;
} data;

vec3 point(Light light, vec3 position, vec3 normal, vec3 eye)
{
    // lighting computation
}

void main()
{
    vec3 color = vec3(0.0f);

    for (int i = 0; i < 5; i++)
    {
        color += point(lights[i], data.position, data.normal, eye);
    }

    pixel = vec4(color, 1.0f);

    vec3 weights = vec3(0.2126f, 0.7152f, 0.0722f);
    float brightness = dot(pixel.rgb, weights);

    if (brightness > 1.0f)
    {
        bloom = vec4(pixel.rgb, 1.0f);
    }
    else
    {
        bloom = vec4(vec3(0.0f), 1.0f);
    }
}

light markers fragment shader

#version 450 core

layout (location = 0) out vec4 pixel;
layout (location = 1) out vec4 bloom;

struct Light
{
    // light properties
};

uniform Light light;

void main()
{
    pixel = vec4(light.diffuse, 1.0f);

    vec3 weights = vec3(0.2126f, 0.7152f, 0.0722f);
    float brightness = dot(pixel.rgb, weights);

    if (brightness > 1.0f)
    {
        bloom = vec4(light.diffuse, 1.0f);
    }
    else
    {
        bloom = vec4(vec3(0.0f), 1.0f);
    }
}

final vertex shader

#version 450 core

layout (location = 0) in vec2 position;
layout (location = 1) in vec2 texcoord;

out FragData
{
    vec2 texcoord;
} data;

void main()
{
    data.texcoord = texcoord;
    gl_Position = vec4(position, 0.0f, 1.0f);
}

final fragment shader

#version 450 core

in FragData
{
    vec2 texcoord;
} data;

out vec4 pixel;

uniform sampler2D scene;
uniform sampler2D bloom;

uniform bool effect;

void main()
{
    vec3 hdr = texture(scene, data.texcoord).rgb;

    if (effect)
    {
        hdr += texture(bloom, data.texcoord).rgb;
    }

    // tone mapping
    float exposure = 1.0f;
    pixel = vec4(vec3(1.0f) - exp(-hdr * exposure), 1.0f);
    // gamma correction
    float gamma = 2.2f;
    pixel = vec4(pow(pixel.rgb, vec3(1.0 / gamma)), 1.0f);
}

目前,我尚未实现模糊以获得布隆效果,但我只是从渲染场景中提取了两个图像并将它们加在一起 .

我哪里做错了?非常感谢你的帮助!

1 回答

  • 2

    你不应该使用

    glBindFramebuffer(GL_FRAMEBUFFER,0);

    因为Qt可能正在使用FBO而不是GL背后的默认帧缓冲 . 您可以使用QOpenGLContext::defaultFramebufferObject查询Qt用作默认帧缓冲区的FBO名称,该名称可能是也可能不是 0 .

相关问题