diff --git a/libs/gfx/include/psemek/gfx/effect/gamma.hpp b/libs/gfx/include/psemek/gfx/effect/gamma.hpp new file mode 100644 index 00000000..3eef76f2 --- /dev/null +++ b/libs/gfx/include/psemek/gfx/effect/gamma.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#include + +namespace psemek::gfx +{ + + struct gamma_correction + { + gamma_correction(); + ~gamma_correction(); + + struct options + { + float gamma = 1.f / 2.2f; + }; + + void invoke(texture_2d const & src, render_target const & dst, options const & opts); + + private: + psemek_declare_pimpl + }; + +} diff --git a/libs/gfx/source/effect/gamma.cpp b/libs/gfx/source/effect/gamma.cpp new file mode 100644 index 00000000..b1e58e5d --- /dev/null +++ b/libs/gfx/source/effect/gamma.cpp @@ -0,0 +1,80 @@ +#include +#include +#include +#include + +namespace psemek::gfx +{ + + static char const gamma_vs[] = +R"(#version 330 + +const vec4 vertices[6] = vec4[6]( + vec4(-1.0, -1.0, 0.0, 1.0), + vec4( 1.0, -1.0, 0.0, 1.0), + vec4( 1.0, 1.0, 0.0, 1.0), + + vec4(-1.0, -1.0, 0.0, 1.0), + vec4( 1.0, 1.0, 0.0, 1.0), + vec4(-1.0, 1.0, 0.0, 1.0) +); + +out vec2 texcoord; + +void main() +{ + gl_Position = vertices[gl_VertexID]; + + texcoord = vertices[gl_VertexID].xy * 0.5 + vec2(0.5); +} +)"; + + static char const gamma_fs[] = +R"(#version 330 + +uniform float u_gamma; +uniform sampler2D u_input; + +in vec2 texcoord; + +out vec4 out_color; + +void main() +{ + vec4 color = texture(u_input, texcoord); + color.rgb = pow(color.rgb, vec3(u_gamma)); + out_color = color; +} +)"; + + struct gamma_correction::impl + { + gfx::program program{gamma_vs, gamma_fs}; + gfx::array array; + }; + + gamma_correction::gamma_correction() + : pimpl_{std::make_unique()} + { + impl().program.bind(); + impl().program["u_input"] = 0; + } + + gamma_correction::~gamma_correction() = default; + + void gamma_correction::invoke(texture_2d const & src, render_target const & dst, options const & opts) + { + gl::Disable(gl::BLEND); + gl::Disable(gl::DEPTH_TEST); + gl::Disable(gl::CULL_FACE); + + dst.bind(); + gl::ActiveTexture(gl::TEXTURE0); + src.bind(); + impl().array.bind(); + impl().program.bind(); + impl().program["u_gamma"] = opts.gamma; + gl::DrawArrays(gl::TRIANGLES, 0, 6); + } + +}