Workbench: Shadow: Add shader variant for manifold case.

Totally Manifold objects only require a single increment/decrement of the
stencil value. This result in less geometry generated and less overdraw.
This commit is contained in:
Clément Foucault 2018-05-21 19:08:02 +02:00
parent 0c9974c8cd
commit 975eac0b07
Notes: blender-bot 2023-04-04 07:45:26 +02:00
Referenced by issue #54931, Workbench: Performance Shadows
4 changed files with 81 additions and 32 deletions

View File

@ -4,8 +4,6 @@
#define USE_INVOC_EXT
#endif
#define DOUBLE_MANIFOLD
#ifdef DOUBLE_MANIFOLD
# ifdef USE_INVOC_EXT
# define invoc_ct 4

View File

@ -4,8 +4,6 @@
#define USE_INVOC_EXT
#endif
#define DOUBLE_MANIFOLD
#ifdef DOUBLE_MANIFOLD
# ifdef USE_INVOC_EXT
# define invoc_ct 2

View File

@ -53,8 +53,11 @@ static struct {
struct GPUShader *prepass_sh_cache[MAX_SHADERS];
struct GPUShader *composite_sh_cache[MAX_SHADERS];
struct GPUShader *shadow_fail_sh;
struct GPUShader *shadow_fail_manifold_sh;
struct GPUShader *shadow_pass_sh;
struct GPUShader *shadow_pass_manifold_sh;
struct GPUShader *shadow_caps_sh;
struct GPUShader *shadow_caps_manifold_sh;
struct GPUTexture *object_id_tx; /* ref only, not alloced */
struct GPUTexture *color_buffer_tx; /* ref only, not alloced */
@ -181,11 +184,23 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
const char *shadow_frag = NULL;
#endif
e_data.shadow_pass_sh = DRW_shader_create(
datatoc_workbench_shadow_vert_glsl,
datatoc_workbench_shadow_geom_glsl,
shadow_frag,
"#define SHADOW_PASS\n"
"#define DOUBLE_MANIFOLD\n");
e_data.shadow_pass_manifold_sh = DRW_shader_create(
datatoc_workbench_shadow_vert_glsl,
datatoc_workbench_shadow_geom_glsl,
shadow_frag,
"#define SHADOW_PASS\n");
e_data.shadow_fail_sh = DRW_shader_create(
datatoc_workbench_shadow_vert_glsl,
datatoc_workbench_shadow_geom_glsl,
shadow_frag,
"#define SHADOW_FAIL\n"
"#define DOUBLE_MANIFOLD\n");
e_data.shadow_fail_manifold_sh = DRW_shader_create(
datatoc_workbench_shadow_vert_glsl,
datatoc_workbench_shadow_geom_glsl,
shadow_frag,
@ -194,7 +209,13 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
datatoc_workbench_shadow_vert_glsl,
datatoc_workbench_shadow_caps_geom_glsl,
shadow_frag,
NULL);
"#define SHADOW_FAIL\n"
"#define DOUBLE_MANIFOLD\n");
e_data.shadow_caps_manifold_sh = DRW_shader_create(
datatoc_workbench_shadow_vert_glsl,
datatoc_workbench_shadow_caps_geom_glsl,
shadow_frag,
"#define SHADOW_FAIL\n");
}
if (!stl->g_data) {
@ -247,8 +268,11 @@ void workbench_deferred_engine_free()
DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]);
}
DRW_SHADER_FREE_SAFE(e_data.shadow_pass_sh);
DRW_SHADER_FREE_SAFE(e_data.shadow_pass_manifold_sh);
DRW_SHADER_FREE_SAFE(e_data.shadow_fail_sh);
DRW_SHADER_FREE_SAFE(e_data.shadow_fail_manifold_sh);
DRW_SHADER_FREE_SAFE(e_data.shadow_caps_sh);
DRW_SHADER_FREE_SAFE(e_data.shadow_caps_manifold_sh);
}
static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp)
@ -308,32 +332,38 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
DRW_shgroup_uniform_float(grp, "shadowShift", &scene->display.shadow_shift, 1);
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
/* Stencil Shadow passes. */
#ifdef DEBUG_SHADOW_VOLUME
psl->shadow_depth_pass_pass = DRW_pass_create(
"Shadow Debug Pass", DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass);
psl->shadow_depth_fail_pass = DRW_pass_create(
"Shadow Debug Fail", DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass);
psl->shadow_depth_fail_caps_pass = DRW_pass_create(
"Shadow Depth Fail Caps", DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass);
DRWState depth_pass_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE;
DRWState depth_fail_state = DRW_STATE_DEPTH_GREATER_EQUAL | DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE;
#else
psl->shadow_depth_pass_pass = DRW_pass_create(
"Shadow Depth Pass", DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_PASS);
DRWState depth_pass_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_PASS;
DRWState depth_fail_state = DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL;
#endif
psl->shadow_depth_pass_pass = DRW_pass_create("Shadow Pass", depth_pass_state);
psl->shadow_depth_pass_mani_pass = DRW_pass_create("Shadow Pass Mani", depth_pass_state);
psl->shadow_depth_fail_pass = DRW_pass_create("Shadow Fail", depth_fail_state);
psl->shadow_depth_fail_mani_pass = DRW_pass_create("Shadow Fail Mani", depth_fail_state);
psl->shadow_depth_fail_caps_pass = DRW_pass_create("Shadow Fail Caps", depth_fail_state);
psl->shadow_depth_fail_caps_mani_pass = DRW_pass_create("Shadow Fail Caps Mani", depth_fail_state);
#ifndef DEBUG_SHADOW_VOLUME
grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass);
DRW_shgroup_stencil_mask(grp, 0xFF);
grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass);
DRW_shgroup_stencil_mask(grp, 0xFF);
psl->shadow_depth_fail_pass = DRW_pass_create(
"Shadow Depth Fail", DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL);
grp = DRW_shgroup_create(e_data.shadow_pass_manifold_sh, psl->shadow_depth_pass_mani_pass);
DRW_shgroup_stencil_mask(grp, 0xFF);
grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass);
DRW_shgroup_stencil_mask(grp, 0xFF);
psl->shadow_depth_fail_caps_pass = DRW_pass_create(
"Shadow Depth Fail Caps", DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL);
grp = DRW_shgroup_create(e_data.shadow_fail_manifold_sh, psl->shadow_depth_fail_mani_pass);
DRW_shgroup_stencil_mask(grp, 0xFF);
grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass);
DRW_shgroup_stencil_mask(grp, 0xFF);
grp = DRW_shgroup_create(e_data.shadow_caps_manifold_sh, psl->shadow_depth_fail_caps_mani_pass);
DRW_shgroup_stencil_mask(grp, 0xFF);
psl->composite_shadow_pass = DRW_pass_create(
"Composite Shadow", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL);
psl->composite_shadow_pass = DRW_pass_create("Composite Shadow", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL);
grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_shadow_pass);
DRW_shgroup_stencil_mask(grp, 0x00);
workbench_composite_uniforms(wpd, grp);
@ -519,20 +549,38 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
mul_v3_mat3_m4v3(engine_object_data->shadow_dir, ob->imat, e_data.display.light_direction);
DRWShadingGroup *grp;
if (!is_manifold) {
grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass);
/* TODO(fclem): only use shadow pass technique if camera is not in shadow. */
const bool use_shadow_pass_technique = true;
if (use_shadow_pass_technique) {
if (is_manifold) {
grp = DRW_shgroup_create(e_data.shadow_pass_manifold_sh, psl->shadow_depth_pass_mani_pass);
}
else {
grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass);
}
DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1);
DRW_shgroup_call_object_add(grp, geom_shadow, ob);
}
else {
struct Gwn_Batch *geom_caps = DRW_cache_object_surface_get(ob);
if (geom_caps) {
grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass);
/* TODO(fclem): only use caps if they are in the view frustum. */
const bool need_caps = true;
if (need_caps) {
if (is_manifold) {
grp = DRW_shgroup_create(e_data.shadow_caps_manifold_sh, psl->shadow_depth_fail_caps_mani_pass);
}
else {
grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass);
}
DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1);
DRW_shgroup_call_object_add(grp, geom_caps, ob);
DRW_shgroup_call_object_add(grp, DRW_cache_object_surface_get(ob), ob);
}
grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass);
if (is_manifold) {
grp = DRW_shgroup_create(e_data.shadow_fail_manifold_sh, psl->shadow_depth_fail_mani_pass);
}
else {
grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass);
}
DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1);
DRW_shgroup_call_object_add(grp, geom_shadow, ob);
}
@ -578,14 +626,16 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata)
#ifdef DEBUG_SHADOW_VOLUME
GPU_framebuffer_bind(fbl->composite_fb);
DRW_draw_pass(psl->composite_pass);
DRW_draw_pass(psl->shadow_depth_pass_pass);
DRW_draw_pass(psl->shadow_depth_fail_pass);
DRW_draw_pass(psl->shadow_depth_fail_caps_pass);
#else
GPU_framebuffer_bind(dfbl->depth_only_fb);
#endif
DRW_draw_pass(psl->shadow_depth_pass_pass);
DRW_draw_pass(psl->shadow_depth_pass_mani_pass);
DRW_draw_pass(psl->shadow_depth_fail_pass);
DRW_draw_pass(psl->shadow_depth_fail_mani_pass);
DRW_draw_pass(psl->shadow_depth_fail_caps_pass);
DRW_draw_pass(psl->shadow_depth_fail_caps_mani_pass);
#ifndef DEBUG_SHADOW_VOLUME
GPU_framebuffer_bind(fbl->composite_fb);
DRW_draw_pass(psl->composite_pass);
DRW_draw_pass(psl->composite_shadow_pass);

View File

@ -70,8 +70,11 @@ typedef struct WORKBENCH_PassList {
/* deferred rendering */
struct DRWPass *prepass_pass;
struct DRWPass *shadow_depth_pass_pass;
struct DRWPass *shadow_depth_pass_mani_pass;
struct DRWPass *shadow_depth_fail_pass;
struct DRWPass *shadow_depth_fail_mani_pass;
struct DRWPass *shadow_depth_fail_caps_pass;
struct DRWPass *shadow_depth_fail_caps_mani_pass;
struct DRWPass *composite_pass;
struct DRWPass *composite_shadow_pass;