File scene_framebuffer.cpp
File List > gui > scene_framebuffer.cpp
Go to the documentation of this file
#include "gui/scene_framebuffer.hpp"
#include <QOpenGLShader>
#include <iostream>
#include "gui/gl_check.hpp"
namespace {
const char* SCENE_COMPOSITE_VERTEX_SHADER = R"(
#version 330 core
out vec2 tex_coord;
void main() {
const vec2 positions[3] = vec2[](
vec2(-1.0, -1.0),
vec2( 3.0, -1.0),
vec2(-1.0, 3.0));
tex_coord = 0.5 * positions[gl_VertexID] + 0.5;
gl_Position = vec4(positions[gl_VertexID], 0.0, 1.0);
}
)";
const char* SCENE_COMPOSITE_FRAGMENT_SHADER = R"(
#version 330 core
in vec2 tex_coord;
uniform sampler2D scene_color;
uniform vec3 background_color;
out vec4 frag_color;
void main() {
vec4 scene = texture(scene_color, tex_coord);
vec3 straight_rgb = scene.a > 1e-5 ? scene.rgb / scene.a : vec3(0.0);
frag_color = vec4(mix(background_color, straight_rgb, scene.a), 1.0);
}
)";
} // namespace
void SceneFramebuffer::ensure_compositor(QOpenGLFunctions* f) {
if (m_compositor_ready) {
return;
}
m_compositor_shader = std::make_unique<QOpenGLShaderProgram>();
if (!m_compositor_shader->addShaderFromSourceCode(QOpenGLShader::Vertex,
SCENE_COMPOSITE_VERTEX_SHADER) ||
!m_compositor_shader->addShaderFromSourceCode(QOpenGLShader::Fragment,
SCENE_COMPOSITE_FRAGMENT_SHADER) ||
!m_compositor_shader->link()) {
std::cerr << "Scene compositor shader error: " << m_compositor_shader->log().toStdString()
<< std::endl;
m_compositor_shader.reset();
return;
}
m_scene_color_loc = m_compositor_shader->uniformLocation("scene_color");
m_background_color_loc = m_compositor_shader->uniformLocation("background_color");
m_compositor_vao.create();
(void)f;
m_compositor_ready = true;
}
void SceneFramebuffer::composite_to_widget_fbo(QOpenGLExtraFunctions* gl, GLuint widget_fbo,
int width, int height) {
if (!m_fbo || widget_fbo == 0) {
return;
}
ensure_compositor(gl);
if (!m_compositor_ready || !m_compositor_shader) {
blit_to_widget_fbo(widget_fbo, width, height);
return;
}
CHECK_GL(gl->glBindFramebuffer(GL_FRAMEBUFFER, widget_fbo));
CHECK_GL(gl->glViewport(0, 0, width, height));
CHECK_GL(gl->glDisable(GL_BLEND));
CHECK_GL(gl->glDisable(GL_DEPTH_TEST));
m_compositor_shader->bind();
CHECK_GL_AFTER();
CHECK_GL(gl->glActiveTexture(GL_TEXTURE0));
CHECK_GL(gl->glBindTexture(GL_TEXTURE_2D, m_fbo->texture()));
m_compositor_shader->setUniformValue(m_scene_color_loc, 0);
m_compositor_shader->setUniformValue(m_background_color_loc, 0.2f, 0.2f, 0.2f);
QOpenGLVertexArrayObject::Binder vao_binder(&m_compositor_vao);
CHECK_GL(gl->glDrawArrays(GL_TRIANGLES, 0, 3));
m_compositor_shader->release();
CHECK_GL_AFTER();
CHECK_GL(gl->glBindTexture(GL_TEXTURE_2D, 0));
CHECK_GL(gl->glEnable(GL_DEPTH_TEST));
}