Workbench Next: Fix Overlay composition

Set "In Front" objects depth to 0,
so overlays are not drawn on top of them.
This commit is contained in:
Miguel Pozo
2023-07-04 21:06:47 +02:00
parent 6335af74f2
commit 3d62888ed6
9 changed files with 64 additions and 44 deletions

View File

@@ -583,6 +583,7 @@ set(GLSL_SRC
engines/workbench/shaders/workbench_material_lib.glsl
engines/workbench/shaders/workbench_merge_infront_frag.glsl
engines/workbench/shaders/workbench_next_merge_depth_frag.glsl
engines/workbench/shaders/workbench_overlay_depth_frag.glsl
engines/workbench/shaders/workbench_prepass_frag.glsl
engines/workbench/shaders/workbench_prepass_hair_vert.glsl
engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl

View File

@@ -0,0 +1,13 @@
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "gpu_shader_create_info.hh"
GPU_SHADER_CREATE_INFO(workbench_overlay_depth)
.sampler(0, ImageType::DEPTH_2D, "depth_tx")
.sampler(1, ImageType::UINT_2D, "stencil_tx")
.fragment_source("workbench_overlay_depth_frag.glsl")
.additional_info("draw_fullscreen")
.depth_write(DepthWrite::ANY)
.do_static_compilation(true);

View File

@@ -0,0 +1,15 @@
/* Prepare the Depth Buffer for the Overlay Engine. */
void main()
{
uint stencil = texelFetch(stencil_tx, ivec2(gl_FragCoord.xy), 0).r;
if (stencil != 0) {
/* Set the depth to 0 for "In Front" objects,
* so the Overlay engine doesn't draw on top of them. */
gl_FragDepth = 0.0;
}
else {
float depth = texelFetch(depth_tx, ivec2(gl_FragCoord.xy), 0).r;
gl_FragDepth = depth;
}
}

View File

@@ -115,6 +115,7 @@ AntiAliasingPass::AntiAliasingPass()
smaa_edge_detect_sh_ = GPU_shader_create_from_info_name("workbench_smaa_stage_0");
smaa_aa_weight_sh_ = GPU_shader_create_from_info_name("workbench_smaa_stage_1");
smaa_resolve_sh_ = GPU_shader_create_from_info_name("workbench_smaa_stage_2");
overlay_depth_sh_ = GPU_shader_create_from_info_name("workbench_overlay_depth");
smaa_search_tx_.ensure_2d(
GPU_R8, {SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT}, GPU_TEXTURE_USAGE_SHADER_READ);
@@ -143,6 +144,13 @@ void AntiAliasingPass::init(const SceneState &scene_state)
void AntiAliasingPass::sync(SceneResources &resources, int2 resolution)
{
overlay_depth_ps_.init();
overlay_depth_ps_.state_set(DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
overlay_depth_ps_.shader_set(overlay_depth_sh_);
overlay_depth_ps_.bind_texture("depth_tx", &resources.depth_tx);
overlay_depth_ps_.bind_texture("stencil_tx", &stencil_tx_);
overlay_depth_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
if (!enabled_) {
taa_accumulation_tx_.free();
sample0_depth_tx_.free();
@@ -244,12 +252,16 @@ void AntiAliasingPass::draw(Manager &manager,
GPUTexture *depth_tx,
GPUTexture *color_tx)
{
auto draw_overlay_depth = [&](GPUTexture *target) {
stencil_tx_ = resources.depth_tx.stencil_view();
overlay_depth_fb_.ensure(GPU_ATTACHMENT_TEXTURE(target));
overlay_depth_fb_.bind();
manager.submit(overlay_depth_ps_);
};
if (!enabled_) {
/* TODO(@pragma37): Should render to the input color_tx and depth_tx in the first place.
* This requires the use of TextureRefs with stencil_view() support,
* but whether TextureRef will stay is still TBD. */
GPU_texture_copy(color_tx, resources.color_tx);
GPU_texture_copy(depth_tx, resources.depth_tx);
draw_overlay_depth(depth_tx);
return;
}
@@ -273,20 +285,10 @@ void AntiAliasingPass::draw(Manager &manager,
}
if (sample_ == 0) {
if (sample0_depth_tx_.is_valid()) {
GPU_texture_copy(sample0_depth_tx_, resources.depth_tx);
}
/* TODO(@pragma37): Should render to the input depth_tx in the first place
* This requires the use of TextureRef with stencil_view() support,
* but whether TextureRef will stay is still TBD. */
/* Copy back the saved depth buffer for correct overlays. */
GPU_texture_copy(depth_tx, resources.depth_tx);
}
else {
/* Copy back the saved depth buffer for correct overlays. */
GPU_texture_copy(depth_tx, sample0_depth_tx_);
draw_overlay_depth(sample0_depth_tx_);
}
/* Copy back the saved depth buffer for correct overlays. */
GPU_texture_copy(depth_tx, sample0_depth_tx_);
if (!DRW_state_is_image_render() || last_sample) {
smaa_weight_tx_.acquire(

View File

@@ -212,15 +212,11 @@ class Instance {
if (scene_state.xray_mode || is_transparent) {
if (in_front) {
draw_callback(transparent_ps.accumulation_in_front_ps_);
if (scene_state.draw_transparent_depth) {
draw_callback(transparent_depth_ps.in_front_ps_);
}
draw_callback(transparent_depth_ps.in_front_ps_);
}
else {
draw_callback(transparent_ps.accumulation_ps_);
if (scene_state.draw_transparent_depth) {
draw_callback(transparent_depth_ps.main_ps_);
}
draw_callback(transparent_depth_ps.main_ps_);
}
}
else {
@@ -472,12 +468,8 @@ class Instance {
}
}
opaque_ps.draw(manager,
view,
resources,
resolution,
&shadow_ps,
transparent_ps.accumulation_ps_.is_empty());
opaque_ps.draw(
manager, view, resources, resolution, scene_state.draw_shadows ? &shadow_ps : nullptr);
transparent_ps.draw(manager, view, resources, resolution);
transparent_depth_ps.draw(manager, view, resources);

View File

@@ -149,8 +149,7 @@ void OpaquePass::draw(Manager &manager,
View &view,
SceneResources &resources,
int2 resolution,
ShadowPass *shadow_pass,
bool accumulation_ps_is_empty)
ShadowPass *shadow_pass)
{
if (is_empty()) {
return;
@@ -189,8 +188,7 @@ void OpaquePass::draw(Manager &manager,
manager.submit(gbuffer_ps_, view);
}
bool needs_stencil_copy = shadow_pass && !gbuffer_in_front_ps_.is_empty() &&
!accumulation_ps_is_empty;
bool needs_stencil_copy = shadow_pass && !gbuffer_in_front_ps_.is_empty();
if (needs_stencil_copy) {
shadow_depth_stencil_tx.ensure_2d(GPU_DEPTH24_STENCIL8,
@@ -201,18 +199,15 @@ void OpaquePass::draw(Manager &manager,
GPU_texture_copy(shadow_depth_stencil_tx, resources.depth_tx);
deferred_ps_stencil_tx = shadow_depth_stencil_tx.stencil_view();
}
else {
shadow_depth_stencil_tx.free();
deferred_ps_stencil_tx = resources.depth_tx.stencil_view();
}
if (shadow_pass && !gbuffer_in_front_ps_.is_empty()) {
opaque_fb.ensure(GPU_ATTACHMENT_TEXTURE(deferred_ps_stencil_tx));
opaque_fb.bind();
GPU_framebuffer_clear_stencil(opaque_fb, 0);
}
else {
shadow_depth_stencil_tx.free();
deferred_ps_stencil_tx = resources.depth_tx.stencil_view();
}
if (shadow_pass) {
shadow_pass->draw(

View File

@@ -88,7 +88,6 @@ struct SceneState {
bool draw_aa = false;
bool draw_object_id = false;
bool draw_transparent_depth = false;
int sample = 0;
int samples_len = 0;
@@ -207,8 +206,7 @@ class OpaquePass {
View &view,
SceneResources &resources,
int2 resolution,
class ShadowPass *shadow_pass,
bool accumulation_ps_is_empty);
class ShadowPass *shadow_pass);
bool is_empty() const;
};
@@ -455,6 +453,7 @@ class AntiAliasingPass {
float weights_sum_ = 0;
Texture sample0_depth_tx_ = {"sample0_depth_tx"};
GPUTexture *stencil_tx_ = nullptr;
Texture taa_accumulation_tx_ = {"taa_accumulation_tx"};
Texture smaa_search_tx_ = {"smaa_search_tx"};
@@ -466,6 +465,7 @@ class AntiAliasingPass {
Framebuffer smaa_edge_fb_ = {"smaa_edge_fb"};
Framebuffer smaa_weight_fb_ = {"smaa_weight_fb"};
Framebuffer smaa_resolve_fb_ = {"smaa_resolve_fb"};
Framebuffer overlay_depth_fb_ = {"overlay_depth_fb"};
float4 smaa_viewport_metrics_ = float4(0);
float smaa_mix_factor_ = 0;
@@ -474,11 +474,13 @@ class AntiAliasingPass {
GPUShader *smaa_edge_detect_sh_ = nullptr;
GPUShader *smaa_aa_weight_sh_ = nullptr;
GPUShader *smaa_resolve_sh_ = nullptr;
GPUShader *overlay_depth_sh_ = nullptr;
PassSimple taa_accumulation_ps_ = {"TAA.Accumulation"};
PassSimple smaa_edge_detect_ps_ = {"SMAA.EdgeDetect"};
PassSimple smaa_aa_weight_ps_ = {"SMAA.BlendWeights"};
PassSimple smaa_resolve_ps_ = {"SMAA.Resolve"};
PassSimple overlay_depth_ps_ = {"Overlay Depth"};
public:
AntiAliasingPass();

View File

@@ -173,7 +173,6 @@ void SceneState::init(Object *camera_ob /*= nullptr*/)
draw_dof = camera && camera->dof.flag & CAM_DOF_ENABLED &&
shading.flag & V3D_SHADING_DEPTH_OF_FIELD;
draw_transparent_depth = draw_outline || draw_dof;
draw_object_id = draw_outline || draw_curvature;
};

View File

@@ -679,6 +679,7 @@ set(SRC_SHADER_CREATE_INFOS
../draw/engines/workbench/shaders/infos/workbench_effect_dof_info.hh
../draw/engines/workbench/shaders/infos/workbench_effect_outline_info.hh
../draw/engines/workbench/shaders/infos/workbench_merge_infront_info.hh
../draw/engines/workbench/shaders/infos/workbench_overlay_depth_info.hh
../draw/engines/workbench/shaders/infos/workbench_prepass_info.hh
../draw/engines/workbench/shaders/infos/workbench_shadow_info.hh
../draw/engines/workbench/shaders/infos/workbench_transparent_resolve_info.hh