Commit 205b3018 authored by Johannes Braun's avatar Johannes Braun
Browse files

Added DOF, vignette Post Processing and framebuffer resizing.

parent 44aaf0d7
......@@ -4,7 +4,7 @@ Size=353,64
Collapsed=0
[Scene]
Pos=-3,66
Pos=-4,66
Size=352,837
Collapsed=0
......
#version 430
#extension GL_ARB_shading_language_include : require
#extension GL_ARB_bindless_texture : require
uniform sampler2DMS source_depth;
uniform int depth_samples = 1;
uniform sampler2D unfiltered;
uniform sampler2D blurred;
uniform float focus_distance = 10.f;
uniform float near = 0.01f;
uniform float far = 100.f;
layout(location = 0) out vec4 output_color;
void main() {
ivec2 pixel = ivec2(gl_FragCoord.xy);
float depth = 0.f;
for (int s = 0; s < depth_samples; ++s)
{
depth += texelFetch(source_depth, pixel, s).r;
}
depth /= depth_samples;
float val = pow(focus_distance / (far - near), 2);
float factor = smoothstep(1.f - val + 0.008f, 1.f, abs(depth)) + smoothstep(1.f - val, 1.f - val - 0.2f, abs(depth));
vec4 color_unf = texelFetch(unfiltered, pixel, 0);
vec4 color_blr = texelFetch(blurred, pixel, 0);
output_color = mix(color_unf, color_blr, factor);
}
#version 430
#extension GL_ARB_shading_language_include : require
#extension GL_ARB_bindless_texture : require
uniform sampler2D source_texture;
uniform vec2 source_size;
uniform float falloff_begin = 0.5f;
uniform float falloff_end = 1.f;
uniform vec3 vignette_tint = vec3(0.15f, 0.11f, 0.07f);
uniform float vignette_strength = 0.5f;
uniform float color_shift = 3.f;
layout(location=0) out vec4 output_color;
const vec3 luma = vec3(0.2126, 0.7152, 0.0722);
void main() {
ivec2 pixel = ivec2(gl_FragCoord.xy);
vec2 relative = vec2(pixel) / source_size;
relative = relative * 2 - 1;
float dist = length(relative);
float dist_factor = smoothstep(0.5f, 1.f, dist);
float color_offset = dist_factor * color_shift;
int offset_x_pos = (pixel.x + int(color_offset));
offset_x_pos = offset_x_pos >= source_size.x ? int(source_size.x - color_offset) : offset_x_pos;
int offset_x_neg = abs(pixel.x - int(color_offset));
int offset_y_pos = (pixel.y + int(color_offset));
offset_y_pos = offset_y_pos >= source_size.y ? int(source_size.y - color_offset) : offset_y_pos;
int offset_y_neg = abs(pixel.y - int(color_offset));
float color_r = texelFetch(source_texture, ivec2(offset_x_pos, pixel.y), 0).r;
color_r += texelFetch(source_texture, ivec2(pixel.x, offset_y_pos), 0).r;
color_r *= 0.5f;
vec2 color_ga = texelFetch(source_texture, pixel, 0).ga;
float color_b = texelFetch(source_texture, ivec2(offset_x_neg, pixel.y), 0).b;
color_b += texelFetch(source_texture, ivec2(pixel.x, offset_y_neg), 0).b;
color_b *= 0.5f;
output_color = vec4(color_r, color_ga.x, color_b, color_ga.y);
output_color = mix(output_color, vec4(vignette_tint * vec3(dot(luma, output_color.rgb)), 1), vignette_strength * dist_factor);
}
......@@ -17,7 +17,7 @@ int main(int argc, char* argv[])
core::Context::createAsCurrent(files::asset("/preferences/default.xml"));
// Load a scene and attach it to the constant root
core::Context::current().graph()->attach(core::global_resources::scenes.get(files::asset("meshes/scenery/House.dae"), 1.0f));
core::Context::current().graph()->attach(core::global_resources::scenes.get(files::asset("meshes/scenery/temple.dae"), 1.0f));
// Create a skybox
core::Context::current().skybox()->reset(files::asset("textures/ryfjallet/"));
......
......@@ -23,6 +23,8 @@ namespace glare::core
{
if (width == m_width && height == m_height && samples == m_samples)
return;
m_draw_buffers.clear();
m_handle.regenerate();
m_width = width;
m_height = height;
m_samples = samples;
......@@ -30,23 +32,29 @@ namespace glare::core
for (auto &&texture : m_color_attachments) {
if (m_samples == 1)
{
texture.second = std::make_shared<Texture>(Texture::Target::e2D, Texture::StoreFormat::eRGBA32Float);
texture.second->set(gl::ImageTarget::e2D, Image<float>({ static_cast<int>(width), static_cast<int>(height) }, 4));
}
else
{
texture.second = std::make_shared<Texture>(Texture::Target::e2DMultisample, Texture::StoreFormat::eRGBA32Float);
texture.second->set(gl::ImageTargetMultisample::e2DMultisample, Image<float>({ static_cast<int>(width), static_cast<int>(height) }, 4, samples));
}
putAttachment(texture.first, texture.second->id());
}
if (m_depth_attachment) {
if (m_samples == 1)
{
m_depth_attachment = std::make_shared<Texture>(Texture::Target::e2D, Texture::StoreFormat::eDepthComponent32Float);
m_depth_attachment->set(gl::ImageTarget::e2D, Image<float>({ static_cast<int>(width), static_cast<int>(height) }, 4));
}
else
{
m_depth_attachment = std::make_shared<Texture>(Texture::Target::e2DMultisample, Texture::StoreFormat::eDepthComponent32Float);
m_depth_attachment->set(gl::ImageTargetMultisample::e2DMultisample, Image<float>({ static_cast<int>(width), static_cast<int>(height) }, 4, samples));
}
gl::namedFramebufferTexture(m_handle, gl::Attachment::eDepth, m_depth_attachment->id(), 0);
}
}
......@@ -141,7 +149,7 @@ namespace glare::core
if (std::find(m_draw_buffers.begin(), m_draw_buffers.end(), attachment) == m_draw_buffers.end()) {
m_draw_buffers.push_back(attachment);
gl::namedFramebufferDrawBuffers(m_handle, m_draw_buffers);
}
}
gl::FramebufferStatus status;
if ((status = gl::checkNamedFramebufferStatus(m_handle, gl::FramebufferTarget::eDraw)) != gl::FramebufferStatus::eComplete)
......
......@@ -31,7 +31,7 @@ namespace glare::core
gl::textureParameter(m_handle, gl::TextureParameter::eCompareMode, m_latest_parameters.compare_mode);
gl::textureParameter(m_handle, gl::TextureParameter::eCompareFunc, m_latest_parameters.compare_func);
gl::generateTextureMipmap(m_handle);
//gl::generateTextureMipmap(m_handle);
}
unsigned Texture::id() const
......@@ -64,7 +64,7 @@ namespace glare::core
{
if (!imageResident())
{
gl::ImageUnitFormat image_format = [this]() {
const gl::ImageUnitFormat image_format = [this]() {
switch (m_format)
{
case StoreFormat::eRGB32Float:
......
......@@ -308,8 +308,16 @@ namespace glare::core
m_components = image.components();
gl::pixelStorei(gl::PixelStoreAlignment::eUnpack, 1);
gl::textureImage(m_handle, t, image.samples(), m_format, { image.width(), image.height(), image.depth() });
apply(std::move(parameters));
glGetError();
glGetError();
glGetError();
glGetError();
gl::textureImage(m_handle, t, image.samples(), m_format, { image.width(), image.height(), image.depth() });
auto x = gl::getError();
x = gl::getError();
}
template<typename T> void Texture::set(SubTarget t, const Image<T>& image)
......@@ -356,10 +364,12 @@ namespace glare::core
m_height = image.height();
m_depth = image.depth();
gl::pixelStorei(gl::PixelStoreAlignment::eUnpack, 1);
clear(0);
gl::textureImage(m_handle, t, level, m_format, texture_format, { image.width(), image.height(), image.depth() }, image.data().empty() ? nullptr : image.data().data());
clear(0);
if (!no_apply)
apply(std::move(parameters));
gl::textureImage(m_handle, t, level, m_format, texture_format, { image.width(), image.height(), image.depth() }, image.data().empty() ? nullptr : image.data().data());
gl::generateTextureMipmap(m_handle);
}
......
......@@ -27,7 +27,7 @@ namespace glare::core
const GLFWvidmode * mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
m_gbuffer_framebuffer = std::make_shared<Framebuffer>(static_cast<unsigned>(mode->width), static_cast<unsigned>(mode->height), samples);
m_gbuffer_framebuffer = std::make_shared<Framebuffer>(width, height, samples);
m_gbuffer_framebuffer->attach(gl::Attachment::eColor0);
m_gbuffer_framebuffer->attach(gl::Attachment::eColor1);
m_gbuffer_framebuffer->attach(gl::Attachment::eColor2);
......@@ -36,10 +36,12 @@ namespace glare::core
m_gbuffer_framebuffer->attach(gl::Attachment::eColor5);
m_gbuffer_framebuffer->attach(gl::Attachment::eDepth);
m_composite_framebuffer = std::make_shared<Framebuffer>(static_cast<unsigned>(mode->width), static_cast<unsigned>(mode->height));
m_composite_framebuffer = std::make_shared<Framebuffer>(width, height);
m_composite_framebuffer->attach(gl::Attachment::eColor0);
m_post_process = std::make_unique<PostProcess>(mode->width, mode->height);
m_post_process = std::make_unique<PostProcess>(width, height);
// SSAO
m_post_process->render_passes.push_back({
[](const GBuffer& gbuffer, const Texture& composite_texture, PostProcess& post_process)
{
......@@ -52,30 +54,13 @@ namespace glare::core
ssao_renderer->draw();
post_process.bufferSwap();
static auto blur_1d = TextureRenderer::make(files::shader("screenshader/blur/blur_1d.frag"));
blur_1d->shader().uniform("steps", 6);
blur_1d->shader().uniform("skip", 2);
blur_1d->shader().uniform("rgb_color_texture", post_process.currentBuffer().attachment(gl::Attachment::eColor0).textureAddress());
blur_1d->shader().uniform("axis", 0u);
blur_1d->draw();
post_process.blur2D(6, 2, post_process.currentBuffer().attachment(gl::Attachment::eColor0));
post_process.bufferSwap();
blur_1d->shader().uniform("rgb_color_texture", post_process.currentBuffer().attachment(gl::Attachment::eColor0).textureAddress());
blur_1d->shader().uniform("axis", 1u);
blur_1d->draw();
post_process.bufferSwap();
static auto mult = TextureRenderer::make(files::shader("screenshader/op/mult.frag"));
mult->shader().uniform("texture_one", post_process.currentBuffer().attachment(gl::Attachment::eColor0).textureAddress());
mult->shader().uniform("texture_other", composite_texture.textureAddress());
mult->draw();
post_process.mul(composite_texture);
}
});
// Bloom
m_post_process->render_passes.push_back({
[](const GBuffer& gbuffer, const Texture& composite_texture, PostProcess& post_process)
{
......@@ -84,43 +69,47 @@ namespace glare::core
cutoff->shader().uniform("cutoff", 0.99f);
cutoff->draw();
post_process.bufferSwap();
post_process.blur2D(8, 2, post_process.currentBuffer().attachment(gl::Attachment::eColor0));
post_process.bufferSwap();
static auto blur_1d = TextureRenderer::make(files::shader("screenshader/blur/blur_1d.frag"));
blur_1d->shader().uniform("steps", 8);
blur_1d->shader().uniform("skip", 2);
blur_1d->shader().uniform("rgb_color_texture", post_process.currentBuffer().attachment(gl::Attachment::eColor0).textureAddress());
blur_1d->shader().uniform("axis", 0u);
blur_1d->draw();
post_process.bufferSwap();
post_process.add(composite_texture);
}
});
blur_1d->shader().uniform("rgb_color_texture", post_process.currentBuffer().attachment(gl::Attachment::eColor0).textureAddress());
blur_1d->shader().uniform("axis", 1u);
blur_1d->draw();
// Vignette + Color shift
m_post_process->render_passes.push_back({
[](const GBuffer& gbuffer, const Texture& composite_texture, PostProcess& post_process)
{
static auto vignette = TextureRenderer::make(files::shader("screenshader/vignette/vignette.frag"));
vignette->shader().uniform("source_texture", composite_texture.textureAddress());
vignette->shader().uniform("source_size", glm::vec2(gbuffer.width(), gbuffer.height()));
vignette->shader().uniform("falloff_begin", 0.2f);
vignette->shader().uniform("falloff_end", 0.8f);
vignette->shader().uniform("vignette_tint", glm::vec3(0.3f, 0.1f, 0.05f));
vignette->shader().uniform("vignette_strength", 0.3f);
vignette->shader().uniform("color_shift", 4.f);
vignette->draw();
}
});
// DOF
m_post_process->render_passes.push_back({
[](const GBuffer& gbuffer, const Texture& composite_texture, PostProcess& post_process)
{
post_process.blur2D(8, 2, composite_texture);
post_process.bufferSwap();
static auto add = TextureRenderer::make(files::shader("screenshader/op/add.frag"));
add->shader().uniform("texture_one", composite_texture.textureAddress());
add->shader().uniform("texture_other", post_process.currentBuffer().attachment(gl::Attachment::eColor0).textureAddress());
add->draw();
static auto dof = TextureRenderer::make(files::shader("screenshader/dof/dof.frag"));
dof->shader().uniform("source_depth", gbuffer.framebuffer().attachment(gl::Attachment::eDepth).textureAddress());
dof->shader().uniform("depth_samples", static_cast<int>(gbuffer.framebuffer().samples()));
dof->shader().uniform("unfiltered", composite_texture.textureAddress());
dof->shader().uniform("blurred", post_process.currentBuffer().attachment(gl::Attachment::eColor0).textureAddress());
dof->draw();
}
});
m_lights_buffer = std::make_unique<Buffer>();
//Update all uniforms that won't change anymore...
m_texture_renderer->shader().uniform("u_gbuffer.base_ior", m_gbuffer_framebuffer->attachment(gl::Attachment::eColor0).textureAddress());
m_texture_renderer->shader().uniform("u_gbuffer.rough_metallic_transmit_emit", m_gbuffer_framebuffer->attachment(gl::Attachment::eColor1).textureAddress());
m_texture_renderer->shader().uniform("u_gbuffer.normal", m_gbuffer_framebuffer->attachment(gl::Attachment::eColor2).textureAddress());
m_texture_renderer->shader().uniform("u_gbuffer.modelview_position", m_gbuffer_framebuffer->attachment(gl::Attachment::eColor3).textureAddress());
m_texture_renderer->shader().uniform("u_gbuffer.world_position", m_gbuffer_framebuffer->attachment(gl::Attachment::eColor4).textureAddress());
m_texture_renderer->shader().uniform("u_gbuffer.depth", m_gbuffer_framebuffer->attachment(gl::Attachment::eDepth).textureAddress());
// Those will only be later updated at will when resizing.
m_texture_renderer->shader().uniform("screen.width", m_width);
m_texture_renderer->shader().uniform("screen.height", m_height);
......@@ -158,6 +147,12 @@ namespace glare::core
m_composite_framebuffer->activate();
gl::setEnabled(gl::EnableParameter::eDepthTest, false);
m_texture_renderer->shader().use();
m_texture_renderer->shader().uniform("u_gbuffer.base_ior", m_gbuffer_framebuffer->attachment(gl::Attachment::eColor0).textureAddress());
m_texture_renderer->shader().uniform("u_gbuffer.rough_metallic_transmit_emit", m_gbuffer_framebuffer->attachment(gl::Attachment::eColor1).textureAddress());
m_texture_renderer->shader().uniform("u_gbuffer.normal", m_gbuffer_framebuffer->attachment(gl::Attachment::eColor2).textureAddress());
m_texture_renderer->shader().uniform("u_gbuffer.modelview_position", m_gbuffer_framebuffer->attachment(gl::Attachment::eColor3).textureAddress());
m_texture_renderer->shader().uniform("u_gbuffer.world_position", m_gbuffer_framebuffer->attachment(gl::Attachment::eColor4).textureAddress());
m_texture_renderer->shader().uniform("u_gbuffer.depth", m_gbuffer_framebuffer->attachment(gl::Attachment::eDepth).textureAddress());
m_texture_renderer->shader().storageBuffer("lightsBuffer", *m_lights_buffer);
if (m_skybox->isInitialized()) m_texture_renderer->shader().uniform("environment", m_skybox->texture().textureAddress());
m_texture_renderer->shader().uniform("u_view", core::Context::current().camera()->viewMatrix());
......@@ -205,6 +200,8 @@ namespace glare::core
m_width = width;
m_height = height;
m_gbuffer_framebuffer->resize(width, height, samples);
m_composite_framebuffer->resize(width, height);
m_post_process->resize(width, height);
m_texture_renderer->shader().uniform("screen.width", m_width);
m_texture_renderer->shader().uniform("screen.height", m_height);
m_texture_renderer->shader().uniform("u_samples", samples);
......
#include "post_process.h"
#include "gbuffer.h"
#include <core/base/gl_state.h>
#include <util/files.h>
namespace glare::core
{
......@@ -31,7 +32,7 @@ namespace glare::core
{
// Last pass. Render to screen/last framebuffer before running PP.
bufferSwap();
pass.pass(gbuffer, render_passes.size() > 1 ? m_renderbuffer->attachment(gl::Attachment::eColor0) : input, *this);
pass.pass(gbuffer, render_passes.size() > 1 ? m_renderbuffer->attachment(gl::Attachment::eColor0) : input, *this);
bufferSwap();
activeBuffer().deactivate();
captured_state.release();
......@@ -63,4 +64,37 @@ namespace glare::core
{
return *(m_framebuffers[m_current_framebuffer]);
}
void PostProcess::blur1D(int steps, int skip, int direction, const Texture& texture)
{
static auto blur_1d = TextureRenderer::make(files::shader("screenshader/blur/blur_1d.frag"));
blur_1d->shader().uniform("steps", steps);
blur_1d->shader().uniform("skip", skip);
blur_1d->shader().uniform("rgb_color_texture", texture.textureAddress());
blur_1d->shader().uniform("axis", static_cast<unsigned>(direction));
blur_1d->draw();
}
void PostProcess::blur2D(int steps, int skip, const Texture& texture)
{
blur1D(steps, skip, 0, texture);
bufferSwap();
blur1D(steps, skip, 1, currentBuffer().attachment(gl::Attachment::eColor0));
}
void PostProcess::add(const Texture& texture) const
{
static auto mult = TextureRenderer::make(files::shader("screenshader/op/add.frag"));
mult->shader().uniform("texture_one", currentBuffer().attachment(gl::Attachment::eColor0).textureAddress());
mult->shader().uniform("texture_other", texture.textureAddress());
mult->draw();
}
void PostProcess::mul(const Texture& texture) const
{
static auto mult = TextureRenderer::make(files::shader("screenshader/op/mul.frag"));
mult->shader().uniform("texture_one", currentBuffer().attachment(gl::Attachment::eColor0).textureAddress());
mult->shader().uniform("texture_other", texture.textureAddress());
mult->draw();
}
}
......@@ -19,8 +19,21 @@ namespace glare::core
void bufferSwap();
const Framebuffer& currentBuffer() const;
static void blur1D(int steps, int skip, int direction, const Texture& texture);
void blur2D(int steps, int skip, const Texture& texture);
void add(const Texture& texture) const;
void mul(const Texture& texture) const;
std::vector<Pass> render_passes;
void resize(int width, int height)
{
m_renderbuffer->resize(width, height);
for (auto&& fb : m_framebuffers)
fb->resize(width, height);
}
private:
const Framebuffer& activeBuffer() const;
std::unique_ptr<TextureRenderer> m_renderer;
......
......@@ -135,10 +135,11 @@ namespace glare::core
default:
break;
}
Log_Hint << message;
});
gl::debugMessageControl(gl::DebugSeverity::eNotification, false);
gl::debugMessageControl(gl::DebugSeverity::eLow, false);
//gl::debugMessageControl(gl::DebugSeverity::eNotification, false);
//gl::debugMessageControl(gl::DebugSeverity::eLow, false);
gl::setEnabled(gl::EnableParameter::eMultisample, true);
......@@ -437,7 +438,7 @@ namespace glare::core
void Callbacks::glfwFramebufferSizeCallback(GLFWwindow *window, int width, int height)
{
auto context = reinterpret_cast<Context*>(glfwGetWindowUserPointer(window));
auto context = reinterpret_cast<Context*>(glfwGetWindowUserPointer(window));
context->resize(width, height);
......
......@@ -9,8 +9,8 @@
Window::Window(unsigned int width, unsigned int height, std::string title) { initialize(width, height, title); }
Window::Window() : m_main_window(nullptr), m_vsync(VSync::eOn60), m_width(0), m_height(0) {
} void Window::initialize(unsigned int width, unsigned int height, std::string title) { m_width = width; m_height = height;
glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// To enable some more debug messages and hints //glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true);
glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5); //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// To enable some more debug messages and hints glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true);
// To enable robust buffer access on out-of-bounds accesses. glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS, GLFW_NO_RESET_NOTIFICATION);
if (width * height == 0) glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
m_main_window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
......
......@@ -19,7 +19,8 @@ namespace gl
eInvalidFramebufferOperation = GL_INVALID_FRAMEBUFFER_OPERATION,
eOutOfMemory = GL_OUT_OF_MEMORY,
eStackUnderflow = GL_STACK_UNDERFLOW,
eStackOverflow = GL_STACK_OVERFLOW
eStackOverflow = GL_STACK_OVERFLOW,
eContextLost = GL_CONTEXT_LOST
};
enum class Type : GLenum
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment