Seperate exposure pass from the rest of post processing
This prevents gamma-weirdness with SMAA
This commit is contained in:
parent
b5655efe0e
commit
ecea7f990e
9 changed files with 313 additions and 225 deletions
|
@ -53,4 +53,6 @@ add_shaders(TARGET Renderer
|
|||
shaders/dof.vert.glsl
|
||||
shaders/dof.frag.glsl
|
||||
shaders/histogram.comp.glsl
|
||||
shaders/histogram-average.comp.glsl)
|
||||
shaders/histogram-average.comp.glsl
|
||||
shaders/expose.frag.glsl
|
||||
shaders/expose.vert.glsl)
|
||||
|
|
|
@ -132,6 +132,7 @@ namespace prism {
|
|||
GFXPipeline* sky_pipeline = nullptr;
|
||||
|
||||
// post
|
||||
GFXPipeline* expose_pipeline = nullptr;
|
||||
GFXPipeline* post_pipeline = nullptr;
|
||||
|
||||
// brdf
|
||||
|
|
|
@ -34,6 +34,10 @@ public:
|
|||
GFXFramebuffer* edge_framebuffer = nullptr;
|
||||
GFXFramebuffer* blend_framebuffer = nullptr;
|
||||
|
||||
// intermediary
|
||||
GFXTexture* mid_texture = nullptr;
|
||||
GFXFramebuffer* mid_framebuffer = nullptr;
|
||||
|
||||
// imgui
|
||||
GFXBuffer* vertex_buffer[RT_MAX_FRAMES_IN_FLIGHT] = {};
|
||||
int current_vertex_size[RT_MAX_FRAMES_IN_FLIGHT] = {};
|
||||
|
|
|
@ -197,14 +197,6 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
|
|||
|
||||
commandbuffer->pop_group();
|
||||
|
||||
if (render_options.enable_aa) {
|
||||
commandbuffer->push_group("SMAA");
|
||||
|
||||
smaa_pass->render(commandbuffer, target);
|
||||
|
||||
commandbuffer->pop_group();
|
||||
}
|
||||
|
||||
if (render_options.enable_depth_of_field && dof_pass != nullptr)
|
||||
dof_pass->render(commandbuffer, *scene);
|
||||
|
||||
|
@ -213,76 +205,47 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
|
|||
commandbuffer->end_render_pass();
|
||||
|
||||
// begin auto exposure
|
||||
{
|
||||
commandbuffer->set_compute_pipeline(histogram_pipeline);
|
||||
|
||||
commandbuffer->set_compute_pipeline(histogram_pipeline);
|
||||
commandbuffer->bind_texture(target.offscreenColorTexture, 0);
|
||||
commandbuffer->bind_shader_buffer(histogram_buffer, 0, 1,
|
||||
sizeof(uint32_t) * 256);
|
||||
|
||||
commandbuffer->bind_texture(target.offscreenColorTexture, 0);
|
||||
commandbuffer->bind_shader_buffer(histogram_buffer, 0, 1, sizeof(uint32_t) * 256);
|
||||
const float lum_range =
|
||||
render_options.max_luminance - render_options.min_luminance;
|
||||
|
||||
const float lum_range = render_options.max_luminance - render_options.min_luminance;
|
||||
prism::float4 params =
|
||||
prism::float4(render_options.min_luminance, 1.0f / lum_range,
|
||||
static_cast<float>(render_extent.width),
|
||||
static_cast<float>(render_extent.height));
|
||||
|
||||
prism::float4 params = prism::float4(render_options.min_luminance,
|
||||
1.0f / lum_range,
|
||||
static_cast<float>(render_extent.width),
|
||||
static_cast<float>(render_extent.height));
|
||||
commandbuffer->set_push_constant(¶ms, sizeof(prism::float4));
|
||||
|
||||
commandbuffer->set_push_constant(¶ms, sizeof(prism::float4));
|
||||
commandbuffer->dispatch(
|
||||
static_cast<uint32_t>(
|
||||
std::ceil(static_cast<float>(render_extent.width) / 16.0f)),
|
||||
static_cast<uint32_t>(
|
||||
std::ceil(static_cast<float>(render_extent.height) / 16.0f)),
|
||||
1);
|
||||
|
||||
commandbuffer->dispatch(static_cast<uint32_t>(std::ceil(static_cast<float>(render_extent.width) / 16.0f)),
|
||||
static_cast<uint32_t>(std::ceil(static_cast<float>(render_extent.height) / 16.0f)), 1);
|
||||
commandbuffer->set_compute_pipeline(histogram_average_pipeline);
|
||||
|
||||
commandbuffer->set_compute_pipeline(histogram_average_pipeline);
|
||||
commandbuffer->bind_shader_buffer(histogram_buffer, 0, 1,
|
||||
sizeof(uint32_t) * 256);
|
||||
|
||||
commandbuffer->bind_shader_buffer(histogram_buffer, 0, 1, sizeof(uint32_t) * 256);
|
||||
params = prism::float4(
|
||||
render_options.min_luminance, lum_range,
|
||||
std::clamp(1.0f - std::exp(-(1.0f / 60.0f) * 1.1f), 0.0f, 1.0f),
|
||||
static_cast<float>(render_extent.width * render_extent.height));
|
||||
|
||||
params = prism::float4(render_options.min_luminance,
|
||||
lum_range,
|
||||
std::clamp(1.0f - std::exp(-(1.0f / 60.0f) * 1.1f), 0.0f, 1.0f),
|
||||
static_cast<float>(render_extent.width * render_extent.height));
|
||||
commandbuffer->set_push_constant(¶ms, sizeof(prism::float4));
|
||||
|
||||
commandbuffer->set_push_constant(¶ms, sizeof(prism::float4));
|
||||
commandbuffer->bind_texture(average_luminance_texture, 0);
|
||||
|
||||
commandbuffer->bind_texture(average_luminance_texture, 0);
|
||||
|
||||
commandbuffer->dispatch(1, 1, 1);
|
||||
|
||||
// continue post processing
|
||||
beginInfo.framebuffer = nullptr;
|
||||
beginInfo.render_pass = nullptr;
|
||||
|
||||
commandbuffer->set_render_pass(beginInfo);
|
||||
|
||||
Viewport viewport = {};
|
||||
viewport.width = static_cast<float>(render_extent.width);
|
||||
viewport.height = static_cast<float>(render_extent.height);
|
||||
|
||||
commandbuffer->set_viewport(viewport);
|
||||
|
||||
commandbuffer->set_graphics_pipeline(post_pipeline);
|
||||
|
||||
if (render_options.enable_depth_of_field)
|
||||
commandbuffer->bind_texture(dof_pass->normal_field, 1);
|
||||
else
|
||||
commandbuffer->bind_texture(target.offscreenColorTexture, 1);
|
||||
|
||||
if (render_options.enable_aa) {
|
||||
commandbuffer->bind_texture(target.blend_texture, 3);
|
||||
} else {
|
||||
commandbuffer->bind_texture(dummy_texture, 3);
|
||||
commandbuffer->dispatch(1, 1, 1);
|
||||
}
|
||||
|
||||
if(auto texture = get_requested_texture(PassTextureType::SelectionSobel))
|
||||
commandbuffer->bind_texture(texture, 5);
|
||||
else
|
||||
commandbuffer->bind_texture(dummy_texture, 5);
|
||||
|
||||
commandbuffer->bind_texture(average_luminance_texture, 6);
|
||||
|
||||
if(render_options.enable_depth_of_field)
|
||||
commandbuffer->bind_texture(dof_pass->far_field, 7);
|
||||
else
|
||||
commandbuffer->bind_texture(dummy_texture, 7);
|
||||
|
||||
PostPushConstants pc;
|
||||
pc.options.x = render_options.enable_aa;
|
||||
pc.options.z = render_options.exposure;
|
||||
|
@ -296,11 +259,83 @@ void renderer::render(GFXCommandBuffer* commandbuffer, Scene* scene, RenderTarge
|
|||
const auto [width, height] = render_extent;
|
||||
pc.viewport = prism::float4(1.0f / static_cast<float>(width), 1.0f / static_cast<float>(height), static_cast<float>(width), static_cast<float>(height));
|
||||
|
||||
commandbuffer->set_push_constant(&pc, sizeof(PostPushConstants));
|
||||
// continue post processing
|
||||
// first we want to manually "expose" the scene, otherwise AA wouldn't work properly
|
||||
{
|
||||
beginInfo.framebuffer = target.mid_framebuffer;
|
||||
beginInfo.render_pass = unorm_render_pass;
|
||||
|
||||
commandbuffer->draw(0, 4, 0, 1);
|
||||
commandbuffer->set_render_pass(beginInfo);
|
||||
|
||||
commandbuffer->pop_group();
|
||||
Viewport viewport = {};
|
||||
viewport.width = static_cast<float>(render_extent.width);
|
||||
viewport.height = static_cast<float>(render_extent.height);
|
||||
|
||||
commandbuffer->set_viewport(viewport);
|
||||
|
||||
commandbuffer->set_graphics_pipeline(expose_pipeline);
|
||||
|
||||
commandbuffer->set_push_constant(&pc, sizeof(PostPushConstants));
|
||||
|
||||
if (render_options.enable_depth_of_field)
|
||||
commandbuffer->bind_texture(dof_pass->normal_field, 1);
|
||||
else
|
||||
commandbuffer->bind_texture(target.offscreenColorTexture, 1);
|
||||
|
||||
commandbuffer->bind_texture(average_luminance_texture, 6);
|
||||
|
||||
if(render_options.enable_depth_of_field)
|
||||
commandbuffer->bind_texture(dof_pass->far_field, 7);
|
||||
else
|
||||
commandbuffer->bind_texture(dummy_texture, 7);
|
||||
|
||||
commandbuffer->draw(0, 4, 0, 1);
|
||||
|
||||
commandbuffer->end_render_pass();
|
||||
}
|
||||
|
||||
if (render_options.enable_aa) {
|
||||
commandbuffer->push_group("SMAA");
|
||||
|
||||
smaa_pass->render(commandbuffer, target);
|
||||
|
||||
commandbuffer->pop_group();
|
||||
}
|
||||
|
||||
// now we overlay sobel, and perform smaa
|
||||
{
|
||||
beginInfo.framebuffer = nullptr;
|
||||
beginInfo.render_pass = nullptr;
|
||||
|
||||
commandbuffer->set_render_pass(beginInfo);
|
||||
|
||||
Viewport viewport = {};
|
||||
viewport.width = static_cast<float>(render_extent.width);
|
||||
viewport.height = static_cast<float>(render_extent.height);
|
||||
|
||||
commandbuffer->set_viewport(viewport);
|
||||
|
||||
commandbuffer->set_graphics_pipeline(post_pipeline);
|
||||
|
||||
commandbuffer->bind_texture(target.mid_texture, 1);
|
||||
|
||||
if (render_options.enable_aa) {
|
||||
commandbuffer->bind_texture(target.blend_texture, 3);
|
||||
} else {
|
||||
commandbuffer->bind_texture(dummy_texture, 3);
|
||||
}
|
||||
|
||||
if(auto texture = get_requested_texture(PassTextureType::SelectionSobel))
|
||||
commandbuffer->bind_texture(texture, 5);
|
||||
else
|
||||
commandbuffer->bind_texture(dummy_texture, 5);
|
||||
|
||||
commandbuffer->set_push_constant(&pc, sizeof(PostPushConstants));
|
||||
|
||||
commandbuffer->draw(0, 4, 0, 1);
|
||||
|
||||
commandbuffer->pop_group();
|
||||
}
|
||||
|
||||
commandbuffer->push_group("Extra Passes");
|
||||
|
||||
|
@ -550,51 +585,50 @@ void renderer::create_dummy_texture() {
|
|||
void renderer::create_render_target_resources(RenderTarget& target) {
|
||||
const auto extent = target.get_render_extent();
|
||||
|
||||
GFXTextureCreateInfo textureInfo = {};
|
||||
textureInfo.label = "Offscreen Color";
|
||||
textureInfo.width = extent.width;
|
||||
textureInfo.height = extent.height;
|
||||
textureInfo.format = GFXPixelFormat::RGBA_32F;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled | GFXTextureUsage::Storage;
|
||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
// offscreen
|
||||
{
|
||||
GFXTextureCreateInfo textureInfo = {};
|
||||
textureInfo.label = "Offscreen Color";
|
||||
textureInfo.width = extent.width;
|
||||
textureInfo.height = extent.height;
|
||||
textureInfo.format = GFXPixelFormat::RGBA_32F;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled |
|
||||
GFXTextureUsage::Storage;
|
||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
target.offscreenColorTexture = gfx->create_texture(textureInfo);
|
||||
target.offscreenColorTexture = gfx->create_texture(textureInfo);
|
||||
|
||||
textureInfo.label = "Offscreen Depth";
|
||||
textureInfo.format = GFXPixelFormat::DEPTH_32F;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
||||
textureInfo.label = "Offscreen Depth";
|
||||
textureInfo.format = GFXPixelFormat::DEPTH_32F;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
||||
|
||||
target.offscreenDepthTexture = gfx->create_texture(textureInfo);
|
||||
target.offscreenDepthTexture = gfx->create_texture(textureInfo);
|
||||
|
||||
GFXFramebufferCreateInfo framebufferInfo = {};
|
||||
framebufferInfo.render_pass = offscreen_render_pass;
|
||||
framebufferInfo.attachments.push_back(target.offscreenColorTexture);
|
||||
framebufferInfo.attachments.push_back(target.offscreenDepthTexture);
|
||||
GFXFramebufferCreateInfo framebufferInfo = {};
|
||||
framebufferInfo.render_pass = offscreen_render_pass;
|
||||
framebufferInfo.attachments.push_back(target.offscreenColorTexture);
|
||||
framebufferInfo.attachments.push_back(target.offscreenDepthTexture);
|
||||
|
||||
target.offscreenFramebuffer = gfx->create_framebuffer(framebufferInfo);
|
||||
target.offscreenFramebuffer = gfx->create_framebuffer(framebufferInfo);
|
||||
}
|
||||
|
||||
if(post_pipeline == nullptr) {
|
||||
GFXGraphicsPipelineCreateInfo pipelineInfo = {};
|
||||
pipelineInfo.label = "Post";
|
||||
// mid
|
||||
{
|
||||
GFXTextureCreateInfo textureInfo = {};
|
||||
textureInfo.label = "Mid Color";
|
||||
textureInfo.width = extent.width;
|
||||
textureInfo.height = extent.height;
|
||||
textureInfo.format = GFXPixelFormat::R8G8B8A8_UNORM;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("post.vert"));
|
||||
pipelineInfo.shaders.fragment_src = ShaderSource(prism::path("post.frag"));
|
||||
target.mid_texture = gfx->create_texture(textureInfo);
|
||||
|
||||
pipelineInfo.shader_input.bindings = {
|
||||
{4, GFXBindingType::PushConstant},
|
||||
{1, GFXBindingType::Texture},
|
||||
{2, GFXBindingType::Texture},
|
||||
{3, GFXBindingType::Texture},
|
||||
{5, GFXBindingType::Texture},
|
||||
{6, GFXBindingType::Texture},
|
||||
{7, GFXBindingType::Texture}
|
||||
};
|
||||
GFXFramebufferCreateInfo framebufferInfo = {};
|
||||
framebufferInfo.render_pass = unorm_render_pass;
|
||||
framebufferInfo.attachments.push_back(target.mid_texture);
|
||||
|
||||
pipelineInfo.shader_input.push_constants = {
|
||||
{sizeof(PostPushConstants), 0}
|
||||
};
|
||||
|
||||
post_pipeline = gfx->create_graphics_pipeline(pipelineInfo);
|
||||
target.mid_framebuffer = gfx->create_framebuffer(framebufferInfo);
|
||||
}
|
||||
|
||||
target.sceneBuffer = gfx->create_buffer(nullptr, sizeof(SceneInformation), true, GFXBufferUsage::Storage);
|
||||
|
@ -609,12 +643,9 @@ void renderer::create_post_pipelines() {
|
|||
|
||||
pipelineInfo.shader_input.bindings = {
|
||||
{4, GFXBindingType::PushConstant},
|
||||
{1, GFXBindingType::Texture},
|
||||
{2, GFXBindingType::Texture},
|
||||
{3, GFXBindingType::Texture},
|
||||
{5, GFXBindingType::Texture},
|
||||
{6, GFXBindingType::Texture},
|
||||
{7, GFXBindingType::Texture}
|
||||
{1, GFXBindingType::Texture}, // colorSampler
|
||||
{3, GFXBindingType::Texture}, // blendSampler
|
||||
{5, GFXBindingType::Texture} // sobelSampler
|
||||
};
|
||||
|
||||
pipelineInfo.shader_input.push_constants = {
|
||||
|
@ -622,6 +653,20 @@ void renderer::create_post_pipelines() {
|
|||
};
|
||||
|
||||
post_pipeline = gfx->create_graphics_pipeline(pipelineInfo);
|
||||
|
||||
pipelineInfo.label = "Expose";
|
||||
pipelineInfo.shaders.vertex_src = ShaderSource(prism::path("expose.vert"));
|
||||
pipelineInfo.shaders.fragment_src = ShaderSource(prism::path("expose.frag"));
|
||||
pipelineInfo.render_pass = unorm_render_pass;
|
||||
|
||||
pipelineInfo.shader_input.bindings = {
|
||||
{4, GFXBindingType::PushConstant},
|
||||
{1, GFXBindingType::Texture}, // colorSampler
|
||||
{6, GFXBindingType::Texture}, // averageLuminanceSampler
|
||||
{7, GFXBindingType::Texture} // farFieldSampler
|
||||
};
|
||||
|
||||
expose_pipeline = gfx->create_graphics_pipeline(pipelineInfo);
|
||||
}
|
||||
|
||||
void renderer::create_sky_pipeline() {
|
||||
|
|
|
@ -68,7 +68,7 @@ void SMAAPass::render(GFXCommandBuffer* command_buffer, RenderTarget& target) {
|
|||
command_buffer->set_graphics_pipeline(edge_pipeline);
|
||||
command_buffer->set_push_constant(&pc, sizeof(PushConstant));
|
||||
|
||||
command_buffer->bind_texture(target.offscreenColorTexture, 0); // color
|
||||
command_buffer->bind_texture(target.mid_texture, 0); // color
|
||||
command_buffer->bind_texture(target.offscreenDepthTexture, 1); // depth
|
||||
|
||||
command_buffer->draw(0, 3, 0, 1);
|
||||
|
|
|
@ -10,7 +10,8 @@ layout(binding = 0) uniform sampler2D imageSampler;
|
|||
layout(binding = 1) uniform sampler2D depthSampler;
|
||||
|
||||
void main() {
|
||||
vec2 edge = SMAALumaEdgeDetectionPS(inUV, inOffset, imageSampler, depthSampler);
|
||||
//vec2 edge = SMAALumaEdgeDetectionPS(inUV, inOffset, imageSampler, depthSampler);
|
||||
vec2 edge = SMAADepthEdgeDetectionPS(inUV, inOffset, depthSampler);
|
||||
|
||||
outColor = vec4(edge, 0.0, 1.0);
|
||||
}
|
||||
|
|
119
engine/shaders/expose.frag.glsl
Normal file
119
engine/shaders/expose.frag.glsl
Normal file
|
@ -0,0 +1,119 @@
|
|||
layout(push_constant) uniform PushConstant {
|
||||
vec4 viewport;
|
||||
vec4 options;
|
||||
vec4 transform_ops;
|
||||
};
|
||||
|
||||
#include "common.nocompile.glsl"
|
||||
|
||||
layout (location = 0) in vec2 inUV;
|
||||
layout(location = 1) in vec4 inOffset;
|
||||
|
||||
layout (location = 0) out vec4 outColor;
|
||||
|
||||
layout (binding = 1) uniform sampler2D colorSampler;
|
||||
layout (binding = 6) uniform sampler2D averageLuminanceSampler;
|
||||
layout (binding = 7) uniform sampler2D farFieldSampler;
|
||||
|
||||
// adapted from https://bruop.github.io/exposure/
|
||||
|
||||
vec3 convertRGB2XYZ(vec3 _rgb)
|
||||
{
|
||||
// Reference:
|
||||
// RGB/XYZ Matrices
|
||||
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
|
||||
vec3 xyz;
|
||||
xyz.x = dot(vec3(0.4124564, 0.3575761, 0.1804375), _rgb);
|
||||
xyz.y = dot(vec3(0.2126729, 0.7151522, 0.0721750), _rgb);
|
||||
xyz.z = dot(vec3(0.0193339, 0.1191920, 0.9503041), _rgb);
|
||||
return xyz;
|
||||
}
|
||||
|
||||
vec3 convertXYZ2RGB(vec3 _xyz)
|
||||
{
|
||||
vec3 rgb;
|
||||
rgb.x = dot(vec3( 3.2404542, -1.5371385, -0.4985314), _xyz);
|
||||
rgb.y = dot(vec3(-0.9692660, 1.8760108, 0.0415560), _xyz);
|
||||
rgb.z = dot(vec3( 0.0556434, -0.2040259, 1.0572252), _xyz);
|
||||
return rgb;
|
||||
}
|
||||
|
||||
vec3 convertXYZ2Yxy(vec3 _xyz)
|
||||
{
|
||||
// Reference:
|
||||
// http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_xyY.html
|
||||
float inv = 1.0/dot(_xyz, vec3(1.0, 1.0, 1.0) );
|
||||
return vec3(_xyz.y, _xyz.x*inv, _xyz.y*inv);
|
||||
}
|
||||
|
||||
vec3 convertYxy2XYZ(vec3 _Yxy)
|
||||
{
|
||||
// Reference:
|
||||
// http://www.brucelindbloom.com/index.html?Eqn_xyY_to_XYZ.html
|
||||
vec3 xyz;
|
||||
xyz.x = _Yxy.x*_Yxy.y/_Yxy.z;
|
||||
xyz.y = _Yxy.x;
|
||||
xyz.z = _Yxy.x*(1.0 - _Yxy.y - _Yxy.z)/_Yxy.z;
|
||||
return xyz;
|
||||
}
|
||||
|
||||
vec3 convertRGB2Yxy(vec3 _rgb)
|
||||
{
|
||||
return convertXYZ2Yxy(convertRGB2XYZ(_rgb) );
|
||||
}
|
||||
|
||||
vec3 convertYxy2RGB(vec3 _Yxy)
|
||||
{
|
||||
return convertXYZ2RGB(convertYxy2XYZ(_Yxy) );
|
||||
}
|
||||
|
||||
float reinhard2(float _x, float _whiteSqr)
|
||||
{
|
||||
return (_x * (1.0 + _x/_whiteSqr) ) / (1.0 + _x);
|
||||
}
|
||||
|
||||
void main() {
|
||||
// passthrough
|
||||
if(options.w == 1) {
|
||||
outColor = texture(colorSampler, inUV);
|
||||
return;
|
||||
}
|
||||
|
||||
bool enable_dof = options.w == 2;
|
||||
vec3 sceneColor = vec3(0);
|
||||
if(enable_dof) {
|
||||
sceneColor = texture(farFieldSampler, inUV).rgb;
|
||||
sceneColor += texture(colorSampler, inUV).rgb;
|
||||
} else {
|
||||
sceneColor = texture(colorSampler, inUV).rgb;
|
||||
}
|
||||
|
||||
vec3 hdrColor = sceneColor; // fading removed
|
||||
|
||||
float avg_lum = texture(averageLuminanceSampler, inUV).r;
|
||||
|
||||
vec3 transformed_color = hdrColor;
|
||||
|
||||
if(transform_ops.y == 1) {
|
||||
transformed_color = vec3(1.0) - exp(-transformed_color * options.z);
|
||||
} else if(transform_ops.y == 2) {
|
||||
vec3 Yxy = convertRGB2Yxy(transformed_color);
|
||||
|
||||
// hard-coded for now
|
||||
float whitePoint = 4.0;
|
||||
|
||||
float lp = Yxy.x / (9.6 * avg_lum + 0.0001);
|
||||
|
||||
// Replace this line with other tone mapping functions
|
||||
// Here we applying the curve to the luminance exclusively
|
||||
Yxy.x = reinhard2(lp, whitePoint);
|
||||
|
||||
transformed_color = convertYxy2RGB(Yxy);
|
||||
}
|
||||
|
||||
if(transform_ops.x == 1) {
|
||||
transformed_color = from_linear_to_srgb(transformed_color);
|
||||
}
|
||||
|
||||
outColor = vec4(transformed_color, 1.0);
|
||||
}
|
14
engine/shaders/expose.vert.glsl
Normal file
14
engine/shaders/expose.vert.glsl
Normal file
|
@ -0,0 +1,14 @@
|
|||
layout(push_constant) uniform readonlPushConstant {
|
||||
vec4 viewport;
|
||||
float fade;
|
||||
vec4 transform_ops;
|
||||
};
|
||||
|
||||
layout (location = 0) out vec2 outUV;
|
||||
layout(location = 1) out vec4 outOffset;
|
||||
|
||||
void main() {
|
||||
outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
|
||||
gl_Position = vec4(outUV * 2.0f + -1.0f, 0.0f, 1.0f);
|
||||
outUV.y = 1.0 - outUV.y;
|
||||
}
|
|
@ -20,11 +20,8 @@ layout(location = 1) in vec4 inOffset;
|
|||
layout (location = 0) out vec4 outColor;
|
||||
|
||||
layout (binding = 1) uniform sampler2D colorSampler;
|
||||
layout (binding = 2) uniform sampler2D backSampler;
|
||||
layout (binding = 3) uniform sampler2D blendSampler;
|
||||
layout (binding = 5) uniform sampler2D sobelSampler;
|
||||
layout (binding = 6) uniform sampler2D averageLuminanceSampler;
|
||||
layout (binding = 7) uniform sampler2D farFieldSampler;
|
||||
|
||||
float calculate_sobel() {
|
||||
float x = 1.0 / viewport.z;
|
||||
|
@ -46,81 +43,13 @@ float calculate_sobel() {
|
|||
return sqrt((horizEdge.rgb * horizEdge.rgb) + (vertEdge.rgb * vertEdge.rgb)).r;
|
||||
}
|
||||
|
||||
// adapted from https://bruop.github.io/exposure/
|
||||
|
||||
vec3 convertRGB2XYZ(vec3 _rgb)
|
||||
{
|
||||
// Reference:
|
||||
// RGB/XYZ Matrices
|
||||
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
|
||||
vec3 xyz;
|
||||
xyz.x = dot(vec3(0.4124564, 0.3575761, 0.1804375), _rgb);
|
||||
xyz.y = dot(vec3(0.2126729, 0.7151522, 0.0721750), _rgb);
|
||||
xyz.z = dot(vec3(0.0193339, 0.1191920, 0.9503041), _rgb);
|
||||
return xyz;
|
||||
}
|
||||
|
||||
vec3 convertXYZ2RGB(vec3 _xyz)
|
||||
{
|
||||
vec3 rgb;
|
||||
rgb.x = dot(vec3( 3.2404542, -1.5371385, -0.4985314), _xyz);
|
||||
rgb.y = dot(vec3(-0.9692660, 1.8760108, 0.0415560), _xyz);
|
||||
rgb.z = dot(vec3( 0.0556434, -0.2040259, 1.0572252), _xyz);
|
||||
return rgb;
|
||||
}
|
||||
|
||||
vec3 convertXYZ2Yxy(vec3 _xyz)
|
||||
{
|
||||
// Reference:
|
||||
// http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_xyY.html
|
||||
float inv = 1.0/dot(_xyz, vec3(1.0, 1.0, 1.0) );
|
||||
return vec3(_xyz.y, _xyz.x*inv, _xyz.y*inv);
|
||||
}
|
||||
|
||||
vec3 convertYxy2XYZ(vec3 _Yxy)
|
||||
{
|
||||
// Reference:
|
||||
// http://www.brucelindbloom.com/index.html?Eqn_xyY_to_XYZ.html
|
||||
vec3 xyz;
|
||||
xyz.x = _Yxy.x*_Yxy.y/_Yxy.z;
|
||||
xyz.y = _Yxy.x;
|
||||
xyz.z = _Yxy.x*(1.0 - _Yxy.y - _Yxy.z)/_Yxy.z;
|
||||
return xyz;
|
||||
}
|
||||
|
||||
vec3 convertRGB2Yxy(vec3 _rgb)
|
||||
{
|
||||
return convertXYZ2Yxy(convertRGB2XYZ(_rgb) );
|
||||
}
|
||||
|
||||
vec3 convertYxy2RGB(vec3 _Yxy)
|
||||
{
|
||||
return convertXYZ2RGB(convertYxy2XYZ(_Yxy) );
|
||||
}
|
||||
|
||||
float reinhard2(float _x, float _whiteSqr)
|
||||
{
|
||||
return (_x * (1.0 + _x/_whiteSqr) ) / (1.0 + _x);
|
||||
}
|
||||
|
||||
void main() {
|
||||
// passthrough
|
||||
if(options.w == 1) {
|
||||
outColor = texture(colorSampler, inUV);
|
||||
return;
|
||||
}
|
||||
|
||||
bool enable_dof = options.w == 2;
|
||||
vec3 sceneColor = vec3(0);
|
||||
if(enable_dof) {
|
||||
sceneColor = texture(farFieldSampler, inUV).rgb;
|
||||
sceneColor += texture(colorSampler, inUV).rgb;
|
||||
} else {
|
||||
if(options.x == 1) // enable AA
|
||||
sceneColor = SMAANeighborhoodBlendingPS(inUV, inOffset, colorSampler, blendSampler).rgb;
|
||||
else
|
||||
sceneColor = texture(colorSampler, inUV).rgb;
|
||||
}
|
||||
if(options.x == 1) // enable AA
|
||||
sceneColor = SMAANeighborhoodBlendingPS(inUV, inOffset, colorSampler, blendSampler).rgb;
|
||||
else
|
||||
sceneColor = texture(colorSampler, inUV).rgb;
|
||||
|
||||
float sobel = 0.0;
|
||||
if(textureSize(sobelSampler, 0).x > 1)
|
||||
|
@ -128,32 +57,5 @@ void main() {
|
|||
|
||||
vec3 sobelColor = vec3(0, 1, 1);
|
||||
|
||||
vec3 hdrColor = sceneColor; // fading removed
|
||||
|
||||
float avg_lum = texture(averageLuminanceSampler, inUV).r;
|
||||
|
||||
vec3 transformed_color = hdrColor;
|
||||
|
||||
if(transform_ops.y == 1) {
|
||||
transformed_color = vec3(1.0) - exp(-transformed_color * options.z);
|
||||
} else if(transform_ops.y == 2) {
|
||||
vec3 Yxy = convertRGB2Yxy(transformed_color);
|
||||
|
||||
// hard-coded for now
|
||||
float whitePoint = 4.0;
|
||||
|
||||
float lp = Yxy.x / (9.6 * avg_lum + 0.0001);
|
||||
|
||||
// Replace this line with other tone mapping functions
|
||||
// Here we applying the curve to the luminance exclusively
|
||||
Yxy.x = reinhard2(lp, whitePoint);
|
||||
|
||||
transformed_color = convertYxy2RGB(Yxy);
|
||||
}
|
||||
|
||||
if(transform_ops.x == 1) {
|
||||
transformed_color = from_linear_to_srgb(transformed_color);
|
||||
}
|
||||
|
||||
outColor = vec4(transformed_color + (sobelColor * sobel), 1.0);
|
||||
outColor = vec4(sceneColor + (sobelColor * sobel), 1.0);
|
||||
}
|
||||
|
|
Reference in a new issue