Commit 7659e2ce authored by Florian Oetke's avatar Florian Oetke
Browse files

scotopic color sensitivity

parent bbc233f8
......@@ -75,3 +75,6 @@ comp_shader:tone_mapping_adjustment = shader/bin/tone_mapping_adjustment.comp.sp
comp_shader:tone_mapping_final = shader/bin/tone_mapping_final.comp.spv
comp_shader:tone_mapping_histogram = shader/bin/tone_mapping_histogram.comp.spv
comp_shader:tone_mapping_exposure = shader/bin/tone_mapping_exposure.comp.spv
vert_shader:tone_mapping_scotopic = shader/bin/fullscreen.vert.spv
frag_shader:tone_mapping_scotopic = shader/bin/tone_mapping_scotopic.frag.spv
......@@ -73,14 +73,6 @@ vec3 expose(vec3 color, float threshold) {
vec3 tone_mapping(vec3 color) {
if(ADJUST_HISTOGRAM==1 && pcs.options.w>0.001) {
/*
vec3 cie_color = rgb2cie(color);
float scotopic_lum = cie_color.y * (1.33*(1+(cie_color.y+cie_color.z)/cie_color.x)-1.68);
float min_mesoptic = 0.00031622776f/10;
float max_mesoptic = 3.16227766017f/10;
float alpha = clamp((scotopic_lum-min_mesoptic) / (max_mesoptic-min_mesoptic), 0, 1);
color = mix(vec3(scotopic_lum), color, alpha);
*/
float luminance = ha_luminance(color);
float idx = log(luminance);
idx = clamp(idx, MIN_LOG_LUMINANCE, MAX_LOG_LUMINANCE);
......
......@@ -38,5 +38,12 @@ vec3 rgb2cie(vec3 c) {
m[2] = vec3(0.1805, 0.0722, 0.9505);
return m * c;
}
vec3 cie2rgb(vec3 c) {
mat3 m;
m[0] = vec3(3.2404542, -0.9692660, 0.0556434);
m[1] = vec3(-1.5371385, 1.8760108, -0.2040259);
m[2] = vec3(-0.4985314, 0.0415560, 1.0572252);
return m * c;
}
#endif
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
#include "color_conversion.glsl"
layout(location = 0) in Vertex_data {
vec2 tex_coords;
} vertex_out;
layout(location = 0) out vec4 out_color;
layout(set=1, binding = 0) uniform sampler2D color_sampler;
void main() {
vec3 color = textureLod(color_sampler, vertex_out.tex_coords, 0).rgb;
vec3 cie_color = rgb2cie(color);
float scotopic_lum = cie_color.y * (1.33*(1+(cie_color.y+cie_color.z)/cie_color.x)-1.68);
float min_mesoptic = 0.00031622776f/10/2;
float max_mesoptic = 3.16227766017f/10/2;
float alpha = clamp((scotopic_lum-min_mesoptic) / (max_mesoptic-min_mesoptic), 0.25, 1);
out_color = vec4(mix(vec3(scotopic_lum), color, alpha), 1.0);
}
......@@ -41,8 +41,8 @@ namespace mirrage::renderer {
float exposure_override = 0.f;
bool histogram_adjustment = true;
bool histogram_trim = true;
float min_display_luminance = 1.f / 255.f;
float max_display_luminance = 244.f / 255.f;
float min_display_luminance = 0.005f;
float max_display_luminance = 0.9f;
bool ssao = true;
bool bloom = true;
......
......@@ -12,7 +12,8 @@ namespace mirrage::renderer {
Tone_mapping_pass(Deferred_renderer&,
ecs::Entity_manager&,
util::maybe<Meta_system&>,
graphic::Texture_2D& src);
graphic::Texture_2D& src,
graphic::Render_target_2D& target);
void update(util::Time dt) override;
......@@ -47,6 +48,11 @@ namespace mirrage::renderer {
vk::UniqueDescriptorSetLayout _compute_descriptor_set_layout;
std::vector<graphic::DescriptorSet> _compute_descriptor_set;
// scotopic color sensitivity adaption
graphic::Framebuffer _scotopic_framebuffer;
graphic::Render_pass _scotopic_renderpass;
graphic::DescriptorSet _scotopic_desc_set;
// calculate scene luminance for tone mapping
graphic::Render_target_2D _luminance_buffer;
graphic::Framebuffer _calc_luminance_framebuffer;
......@@ -59,6 +65,7 @@ namespace mirrage::renderer {
vk::UniquePipeline _adjust_histogram_pipeline;
vk::UniquePipeline _build_final_factors_pipeline;
void _scotopic_adaption(vk::DescriptorSet, vk::CommandBuffer&);
void _extract_luminance(vk::DescriptorSet, vk::CommandBuffer&);
void _dispatch_build_histogram(vk::DescriptorSet, vk::CommandBuffer&);
void _dispatch_compute_exposure(vk::DescriptorSet, vk::CommandBuffer&);
......
......@@ -77,6 +77,67 @@ namespace mirrage::renderer {
| vk::AccessFlagBits::eTransferRead);
auto render_pass = builder.build();
out_framebuffer = builder.build_framebuffer(
{target.view(0), util::Rgba{}}, target.width(), target.height());
return render_pass;
}
auto build_scotopic_render_pass(Deferred_renderer& renderer,
vk::DescriptorSetLayout desc_set_layout,
graphic::Render_target_2D& target,
graphic::Framebuffer& out_framebuffer)
{
auto builder = renderer.device().create_render_pass_builder();
auto screen = builder.add_attachment(vk::AttachmentDescription{vk::AttachmentDescriptionFlags{},
renderer.gbuffer().color_format,
vk::SampleCountFlagBits::e1,
vk::AttachmentLoadOp::eDontCare,
vk::AttachmentStoreOp::eStore,
vk::AttachmentLoadOp::eDontCare,
vk::AttachmentStoreOp::eDontCare,
vk::ImageLayout::eUndefined,
vk::ImageLayout::eShaderReadOnlyOptimal});
auto pipeline = graphic::Pipeline_description{};
pipeline.input_assembly.topology = vk::PrimitiveTopology::eTriangleList;
pipeline.multisample = vk::PipelineMultisampleStateCreateInfo{};
pipeline.color_blending = vk::PipelineColorBlendStateCreateInfo{};
pipeline.depth_stencil = vk::PipelineDepthStencilStateCreateInfo{};
pipeline.add_descriptor_set_layout(renderer.global_uniforms_layout());
pipeline.add_descriptor_set_layout(desc_set_layout);
pipeline.add_push_constant(
"pcs"_strid, sizeof(Push_constants), vk::ShaderStageFlagBits::eFragment);
auto& pass = builder.add_subpass(pipeline).color_attachment(screen);
pass.stage("scotopic"_strid)
.shader("frag_shader:tone_mapping_scotopic"_aid, graphic::Shader_stage::fragment)
.shader("vert_shader:tone_mapping_scotopic"_aid, graphic::Shader_stage::vertex);
builder.add_dependency(
util::nothing,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::AccessFlags{},
pass,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite);
builder.add_dependency(
pass,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite,
util::nothing,
vk::PipelineStageFlagBits::eBottomOfPipe,
vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eShaderRead
| vk::AccessFlagBits::eTransferRead);
auto render_pass = builder.build();
out_framebuffer = builder.build_framebuffer(
......@@ -143,7 +204,8 @@ namespace mirrage::renderer {
Tone_mapping_pass::Tone_mapping_pass(Deferred_renderer& renderer,
ecs::Entity_manager&,
util::maybe<Meta_system&>,
graphic::Texture_2D& src)
graphic::Texture_2D& src,
graphic::Render_target_2D& target)
: _renderer(renderer)
, _src(src)
, _compute_fence(renderer.device().create_fence(true))
......@@ -175,6 +237,12 @@ namespace mirrage::renderer {
vk::DescriptorSetLayoutBinding(
2, vk::DescriptorType::eStorageImage, 1, vk::ShaderStageFlagBits::eCompute)}))
, _scotopic_renderpass(build_scotopic_render_pass(renderer,
*_descriptor_set_layout,
target,
_scotopic_framebuffer))
,_scotopic_desc_set(_descriptor_set_layout.create_set(renderer.descriptor_pool(), {src.view()}))
, _luminance_buffer(renderer.device(),
{src.width(), src.height()},
0,
......@@ -188,7 +256,7 @@ namespace mirrage::renderer {
_luminance_format,
_luminance_buffer,
_calc_luminance_framebuffer))
, _calc_luminance_desc_set(_descriptor_set_layout.create_set(renderer.descriptor_pool(), {src.view()}))
, _calc_luminance_desc_set(_descriptor_set_layout.create_set(renderer.descriptor_pool(), {target.view()}))
, _compute_pipeline_layout(build_compute_pipeline_layout(_renderer, *_compute_descriptor_set_layout))
, _build_histogram_pipeline(build_compute_pipeline(_renderer.device(),
......@@ -305,6 +373,7 @@ namespace mirrage::renderer {
_last_result_data.back() = *(reinterpret_cast<float*>(data_addr) + (histogram_buffer_length - 1));
}
_scotopic_adaption(global_uniform_set, command_buffer);
_extract_luminance(global_uniform_set, command_buffer);
_dispatch_build_histogram(global_uniform_set, command_buffer);
_dispatch_compute_exposure(global_uniform_set, command_buffer);
......@@ -337,6 +406,20 @@ namespace mirrage::renderer {
command_buffer.draw(3, 1, 0, 0);
});
}
void Tone_mapping_pass::_scotopic_adaption(vk::DescriptorSet global_uniform_set,
vk::CommandBuffer& command_buffer)
{
auto _ = _renderer.profiler().push("Scotopic Adaption");
// extract luminance of current frame
_scotopic_renderpass.execute(command_buffer, _scotopic_framebuffer, [&] {
auto desc_sets = std::array<vk::DescriptorSet, 2>{global_uniform_set, *_scotopic_desc_set};
_scotopic_renderpass.bind_descriptor_sets(0, desc_sets);
command_buffer.draw(3, 1, 0, 0);
});
}
void Tone_mapping_pass::_dispatch_build_histogram(vk::DescriptorSet global_uniform_set,
vk::CommandBuffer& command_buffer)
{
......@@ -536,9 +619,11 @@ namespace mirrage::renderer {
util::maybe<Meta_system&> meta_system,
bool& write_first_pp_buffer) -> std::unique_ptr<Pass>
{
auto& color_src = !write_first_pp_buffer ? renderer.gbuffer().colorA : renderer.gbuffer().colorB;
auto& color_src = !write_first_pp_buffer ? renderer.gbuffer().colorA : renderer.gbuffer().colorB;
auto& color_dest = !write_first_pp_buffer ? renderer.gbuffer().colorB : renderer.gbuffer().colorA;
write_first_pp_buffer = !write_first_pp_buffer;
return std::make_unique<Tone_mapping_pass>(renderer, entities, meta_system, color_src);
return std::make_unique<Tone_mapping_pass>(renderer, entities, meta_system, color_src, color_dest);
}
auto Tone_mapping_pass_factory::rank_device(vk::PhysicalDevice,
......
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