Add toggle for experimental depth of field effect
This commit is contained in:
parent
24d3ac12c1
commit
91600b5f6f
8 changed files with 143 additions and 24 deletions
|
@ -109,6 +109,9 @@ void draw_renderer() {
|
|||
ImGui::DragFloat("Min Luminance", &render_options.min_luminance);
|
||||
ImGui::DragFloat("Max Luminance", &render_options.max_luminance);
|
||||
|
||||
ImGui::Checkbox("Enable DoF", &render_options.enable_depth_of_field);
|
||||
ImGui::DragFloat("DoF Strength", &render_options.depth_of_field_strength);
|
||||
|
||||
bool should_recompile = false;
|
||||
|
||||
float render_scale = render_options.render_scale;
|
||||
|
|
|
@ -15,6 +15,14 @@ public:
|
|||
|
||||
void render(GFXCommandBuffer* command_buffer, Scene& scene);
|
||||
|
||||
GFXTexture* far_field = nullptr;
|
||||
GFXTexture* normal_field = nullptr;
|
||||
|
||||
GFXFramebuffer* far_framebuffer = nullptr;
|
||||
GFXFramebuffer* normal_framebuffer = nullptr;
|
||||
|
||||
GFXRenderPass* renderpass = nullptr;
|
||||
|
||||
private:
|
||||
Renderer* renderer = nullptr;
|
||||
|
||||
|
|
|
@ -43,6 +43,9 @@ struct RenderOptions {
|
|||
float min_luminance = -8.0f;
|
||||
float max_luminance = 3.0f;
|
||||
|
||||
bool enable_depth_of_field = true;
|
||||
float depth_of_field_strength = 3.0f;
|
||||
|
||||
bool dynamic_resolution = false;
|
||||
double render_scale = 1.0f;
|
||||
|
||||
|
|
|
@ -11,6 +11,11 @@ AssetPtr<Texture> aperture_texture;
|
|||
DoFPass::DoFPass(GFX* gfx, Renderer* renderer) : renderer(renderer) {
|
||||
aperture_texture = assetm->get<Texture>(file::app_domain / "textures/aperture.png");
|
||||
|
||||
GFXRenderPassCreateInfo renderPassInfo = {};
|
||||
renderPassInfo.attachments.push_back(GFXPixelFormat::RGBA_32F);
|
||||
|
||||
renderpass = gfx->create_render_pass(renderPassInfo);
|
||||
|
||||
const auto extent = renderer->get_render_extent();
|
||||
|
||||
GFXShaderConstant width_constant = {};
|
||||
|
@ -24,17 +29,58 @@ DoFPass::DoFPass(GFX* gfx, Renderer* renderer) : renderer(renderer) {
|
|||
create_info.shaders.vertex_path = "dof.vert";
|
||||
create_info.shaders.vertex_constants = {width_constant, height_constant};
|
||||
create_info.shaders.fragment_path = "dof.frag";
|
||||
create_info.render_pass = renderer->viewportRenderPass;
|
||||
|
||||
create_info.shader_input.bindings = {
|
||||
{2, GFXBindingType::PushConstant}
|
||||
};
|
||||
|
||||
create_info.render_pass = renderpass;
|
||||
|
||||
create_info.blending.enable_blending = true;
|
||||
create_info.blending.src_rgb = GFXBlendFactor::SrcAlpha;
|
||||
create_info.blending.dst_rgb = GFXBlendFactor::OneMinusSrcAlpha;
|
||||
create_info.blending.src_rgb = GFXBlendFactor::SrcColor;
|
||||
create_info.blending.dst_rgb = GFXBlendFactor::One;
|
||||
create_info.blending.src_alpha = GFXBlendFactor::SrcAlpha;
|
||||
create_info.blending.dst_alpha = GFXBlendFactor::OneMinusSrcAlpha;
|
||||
create_info.blending.dst_alpha = GFXBlendFactor::One;
|
||||
|
||||
pipeline = gfx->create_graphics_pipeline(create_info);
|
||||
|
||||
GFXTextureCreateInfo textureInfo = {};
|
||||
textureInfo.width = extent.width;
|
||||
textureInfo.height = extent.height;
|
||||
textureInfo.format = GFXPixelFormat::RGBA_32F;
|
||||
textureInfo.usage = GFXTextureUsage::Attachment | GFXTextureUsage::Sampled;
|
||||
textureInfo.samplingMode = SamplingMode::ClampToEdge;
|
||||
|
||||
normal_field = gfx->create_texture(textureInfo);
|
||||
far_field = gfx->create_texture(textureInfo);
|
||||
|
||||
GFXFramebufferCreateInfo framebufferInfo = {};
|
||||
framebufferInfo.render_pass = renderpass;
|
||||
framebufferInfo.attachments = { normal_field };
|
||||
|
||||
normal_framebuffer = gfx->create_framebuffer(framebufferInfo);
|
||||
|
||||
framebufferInfo.attachments = { far_field };
|
||||
|
||||
far_framebuffer = gfx->create_framebuffer(framebufferInfo);
|
||||
}
|
||||
|
||||
void DoFPass::render(GFXCommandBuffer* command_buffer, Scene&) {
|
||||
const auto render_extent = renderer->get_render_extent();
|
||||
|
||||
// render far field
|
||||
GFXRenderPassBeginInfo beginInfo = {};
|
||||
beginInfo.framebuffer = far_framebuffer;
|
||||
beginInfo.render_pass = renderpass;
|
||||
|
||||
command_buffer->set_render_pass(beginInfo);
|
||||
|
||||
Viewport viewport = {};
|
||||
viewport.width = render_extent.width;
|
||||
viewport.height = render_extent.height;
|
||||
|
||||
command_buffer->set_viewport(viewport);
|
||||
|
||||
command_buffer->set_graphics_pipeline(pipeline);
|
||||
|
||||
command_buffer->bind_texture(renderer->offscreenColorTexture, 0);
|
||||
|
@ -43,5 +89,26 @@ void DoFPass::render(GFXCommandBuffer* command_buffer, Scene&) {
|
|||
|
||||
const auto extent = renderer->get_render_extent();
|
||||
|
||||
Vector4 params(render_options.depth_of_field_strength, 0.0, 0.0, 0.0);
|
||||
|
||||
command_buffer->set_push_constant(¶ms, sizeof(Vector4));
|
||||
|
||||
command_buffer->draw(0, 4, 0, extent.width * extent.height);
|
||||
|
||||
// render normal field
|
||||
beginInfo.framebuffer = normal_framebuffer;
|
||||
|
||||
command_buffer->set_render_pass(beginInfo);
|
||||
|
||||
command_buffer->set_graphics_pipeline(pipeline);
|
||||
|
||||
command_buffer->bind_texture(renderer->offscreenColorTexture, 0);
|
||||
command_buffer->bind_texture(renderer->offscreenDepthTexture, 1);
|
||||
command_buffer->bind_texture(aperture_texture->handle, 2);
|
||||
|
||||
params.y = 1;
|
||||
|
||||
command_buffer->set_push_constant(¶ms, sizeof(Vector4));
|
||||
|
||||
command_buffer->draw(0, 4, 0, extent.width * extent.height);
|
||||
}
|
||||
|
|
|
@ -242,7 +242,7 @@ void Renderer::render(Scene* scene, int index) {
|
|||
for(auto& [obj, camera] : cameras) {
|
||||
const int actual_width = render_extent.width / cameras.size();
|
||||
|
||||
camera.perspective = transform::infinite_perspective(radians(camera.fov), static_cast<float>(actual_width) / static_cast<float>(render_extent.height), camera.near);
|
||||
camera.perspective = transform::perspective(radians(camera.fov), static_cast<float>(actual_width) / static_cast<float>(render_extent.height), 0.1f, 100.0f);
|
||||
camera.view = inverse(scene->get<Transform>(obj).model);
|
||||
|
||||
Viewport viewport = {};
|
||||
|
@ -268,6 +268,8 @@ void Renderer::render(Scene* scene, int index) {
|
|||
|
||||
commandbuffer->pop_group();
|
||||
|
||||
dofPass->render(commandbuffer, *scene);
|
||||
|
||||
if(!viewport_mode) {
|
||||
beginInfo.framebuffer = nullptr;
|
||||
beginInfo.render_pass = nullptr;
|
||||
|
@ -311,22 +313,35 @@ void Renderer::render(Scene* scene, int index) {
|
|||
commandbuffer->dispatch(1, 1, 1);
|
||||
|
||||
commandbuffer->set_graphics_pipeline(viewport_mode ? renderToViewportPipeline : postPipeline);
|
||||
commandbuffer->bind_texture(offscreenColorTexture, 1);
|
||||
|
||||
if(render_options.enable_depth_of_field)
|
||||
commandbuffer->bind_texture(dofPass->normal_field, 1);
|
||||
else
|
||||
commandbuffer->bind_texture(offscreenColorTexture, 1);
|
||||
|
||||
commandbuffer->bind_texture(offscreenBackTexture, 2);
|
||||
commandbuffer->bind_texture(smaaPass->blend_texture, 3);
|
||||
|
||||
if(auto texture = get_requested_texture(PassTextureType::SelectionSobel)) {
|
||||
if(auto texture = get_requested_texture(PassTextureType::SelectionSobel))
|
||||
commandbuffer->bind_texture(texture, 4);
|
||||
} else {
|
||||
else
|
||||
commandbuffer->bind_texture(dummyTexture, 4);
|
||||
}
|
||||
|
||||
commandbuffer->bind_texture(average_luminance_texture, 5);
|
||||
|
||||
if(render_options.enable_depth_of_field)
|
||||
commandbuffer->bind_texture(dofPass->far_field, 6);
|
||||
else
|
||||
commandbuffer->bind_texture(dummyTexture, 6);
|
||||
|
||||
PostPushConstants pc;
|
||||
pc.options.x = render_options.enable_aa;
|
||||
pc.options.y = fade;
|
||||
pc.options.z = render_options.exposure;
|
||||
|
||||
if(render_options.enable_depth_of_field)
|
||||
pc.options.w = 2;
|
||||
|
||||
pc.transform_ops.x = (int)render_options.display_color_space;
|
||||
pc.transform_ops.y = (int)render_options.tonemapping;
|
||||
|
||||
|
@ -346,6 +361,7 @@ void Renderer::render(Scene* scene, int index) {
|
|||
|
||||
commandbuffer->draw(0, 4, 0, 1);
|
||||
|
||||
|
||||
commandbuffer->pop_group();
|
||||
|
||||
if(current_screen != nullptr)
|
||||
|
|
|
@ -7,16 +7,22 @@ layout(location = 0) out vec4 outColor;
|
|||
layout(rgba32f, binding = 0) uniform image2D color_sampler;
|
||||
layout(binding = 2) uniform sampler2D aperture_sampler;
|
||||
|
||||
vec4 fromLinear(vec4 linearRGB)
|
||||
{
|
||||
return pow(linearRGB, vec4(1.0/2.2));
|
||||
}
|
||||
layout(push_constant, binding = 2) uniform readonly PushConstant{
|
||||
vec4 params;
|
||||
};
|
||||
|
||||
void main() {
|
||||
/*if(depth < 0.98)
|
||||
discard;*/
|
||||
// far field mode
|
||||
if(params.y == 0) {
|
||||
if(depth < 0.98)
|
||||
discard;
|
||||
}
|
||||
|
||||
if(inUV.y > 1.0 || inUV.x > 1.0)
|
||||
discard;
|
||||
|
||||
outColor = vec4(fromLinear(imageLoad(color_sampler, inPixel)).rgb, 1.0) * texture(aperture_sampler, inUV);
|
||||
outColor = vec4(imageLoad(color_sampler, inPixel).rgb, 1.0);
|
||||
if(params.y == 0) {
|
||||
outColor = outColor * texture(aperture_sampler, inUV);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,10 @@ layout(location = 2) out float outDepth;
|
|||
|
||||
layout(binding = 1) uniform sampler2D depth_sampler;
|
||||
|
||||
layout(push_constant, binding = 2) uniform readonly PushConstant{
|
||||
vec4 params;
|
||||
};
|
||||
|
||||
void main() {
|
||||
outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
|
||||
|
||||
|
@ -17,7 +21,12 @@ void main() {
|
|||
outDepth = depth;
|
||||
|
||||
vec2 pos = vec2(outUV * 2.0 + -1.0);
|
||||
pos *= 5.0 * depth;
|
||||
|
||||
// far field mode
|
||||
if(params.y == 0) {
|
||||
pos *= params.x * depth;
|
||||
}
|
||||
|
||||
pos += vec2(pixel.x, pixel.y);
|
||||
pos *= 2.0 / vec2(width, height);
|
||||
pos += vec2(-1, -1);
|
||||
|
|
|
@ -24,6 +24,7 @@ layout (binding = 2) uniform sampler2D backSampler;
|
|||
layout (binding = 3) uniform sampler2D blendSampler;
|
||||
layout (binding = 4) uniform sampler2D sobelSampler;
|
||||
layout (binding = 5) uniform sampler2D averageLuminanceSampler;
|
||||
layout (binding = 6) uniform sampler2D farFieldSampler;
|
||||
|
||||
float calculate_sobel() {
|
||||
float x = 1.0 / viewport.z;
|
||||
|
@ -109,11 +110,17 @@ void main() {
|
|||
return;
|
||||
}
|
||||
|
||||
bool enable_dof = options.w == 2;
|
||||
vec3 sceneColor = vec3(0);
|
||||
if(options.x == 1) // enable AA
|
||||
sceneColor = SMAANeighborhoodBlendingPS(inUV, inOffset, colorSampler, blendSampler).rgb;
|
||||
else
|
||||
sceneColor = texture(colorSampler, inUV).rgb;
|
||||
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;
|
||||
}
|
||||
|
||||
float sobel = 0.0;
|
||||
if(textureSize(sobelSampler, 0).x > 1)
|
||||
|
|
Reference in a new issue