From 301a21a5e13e99a556dd8e73ea88c0546d678627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Mon, 2 Sep 2024 17:00:31 +0200 Subject: [PATCH] add shadow penumbra --- bind/v4k.lua | 1 + demos/09-shadows.c | 2 +- engine/art/shaderlib/light.glsl | 1 + engine/art/shaderlib/shadowmap.glsl | 9 ++++++--- engine/joint/v4k.h | 4 ++++ engine/split/v4k_render.c | 3 +++ engine/split/v4k_render.h | 1 + engine/v4k.c | 3 +++ engine/v4k.h | 1 + 9 files changed, 21 insertions(+), 4 deletions(-) diff --git a/bind/v4k.lua b/bind/v4k.lua index c0df293..fecdc27 100644 --- a/bind/v4k.lua +++ b/bind/v4k.lua @@ -1167,6 +1167,7 @@ typedef struct light_t { float shadow_bias; float normal_bias; float shadow_softness; + float penumbra_size; bool cached; bool processed_shadows; } light_t; diff --git a/demos/09-shadows.c b/demos/09-shadows.c index a3615bd..8893853 100644 --- a/demos/09-shadows.c +++ b/demos/09-shadows.c @@ -109,7 +109,7 @@ int main(int argc, char** argv) { enum { POINT, SPOT, DIR, ALL }; - static unsigned mode = DIR; + static unsigned mode = SPOT; if (!ui_active()) { if (input_down(KEY_1)) mode = POINT; diff --git a/engine/art/shaderlib/light.glsl b/engine/art/shaderlib/light.glsl index fe208d1..f96dfdf 100644 --- a/engine/art/shaderlib/light.glsl +++ b/engine/art/shaderlib/light.glsl @@ -31,6 +31,7 @@ struct light_t { float min_variance; float variance_transition; float shadow_softness; + float penumbra_size; }; const int LIGHT_DIRECTIONAL = 0; diff --git a/engine/art/shaderlib/shadowmap.glsl b/engine/art/shaderlib/shadowmap.glsl index fb96eb8..252c174 100644 --- a/engine/art/shaderlib/shadowmap.glsl +++ b/engine/art/shaderlib/shadowmap.glsl @@ -23,9 +23,12 @@ vec2 shadow_vsm_variance(vec3 dir, int light_index, float distance, float min_va return vec2(linstep(variance_transition, 1.0, variance / (variance + d * d)), moments.x); } -float shadow_vsm(float distance, vec3 dir, int light_index, float min_variance, float variance_transition, float shadow_softness_raw) { - distance = distance / 200; +float shadow_vsm(float distance, vec3 dir, int light_index, float min_variance, float variance_transition, float shadow_softness_raw, float penumbra_size) { + float clamped_distance = clamp(distance, 0.0, 200.0); float shadow_softness = shadow_softness_raw * 10.0; + shadow_softness = mix(shadow_softness, distance * 10.0, penumbra_size); + distance = distance / 200; + // Get the offset coordinates ivec3 ofs_coord = ivec3(0); @@ -207,7 +210,7 @@ vec4 shadowmap(int idx, in vec4 peye, in vec4 neye) { vec3 light_pos = (view * vec4(light.pos, 1.0)).xyz; vec3 dir = light_pos - fragment; vec4 sc = inv_view * vec4(dir, 0.0); - shadowFactor = shadow_vsm(length(dir), -sc.xyz, idx, light.min_variance, light.variance_transition, light.shadow_softness); + shadowFactor = shadow_vsm(length(dir), -sc.xyz, idx, light.min_variance, light.variance_transition, light.shadow_softness, light.penumbra_size); } } diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index d2bd544..54f7ae1 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -17292,6 +17292,7 @@ typedef struct light_t { float shadow_bias; //< CSM float normal_bias; //< CSM float shadow_softness; + float penumbra_size; // internals bool cached; //< used by scene to invalidate cached light data @@ -383306,6 +383307,7 @@ light_t light() { l.shadow_bias = 0.15f; l.normal_bias = 0.05f; l.shadow_softness = 7.0f; + l.penumbra_size = 0.0f; l.min_variance = 0.00002f; l.variance_transition = 0.2f; return l; @@ -383389,6 +383391,7 @@ void light_update(unsigned num_lights, light_t *lv) { shader_float(va("u_lights[%d].shadow_bias", i), lv[i].shadow_bias); shader_float(va("u_lights[%d].normal_bias", i), lv[i].normal_bias); shader_float(va("u_lights[%d].shadow_softness", i), lv[i].shadow_softness); + shader_float(va("u_lights[%d].penumbra_size", i), lv[i].penumbra_size); shader_float(va("u_lights[%d].min_variance", i), lv[i].min_variance); shader_float(va("u_lights[%d].variance_transition", i), lv[i].variance_transition); shader_bool(va("u_lights[%d].processed_shadows", i), lv[i].processed_shadows); @@ -383417,6 +383420,7 @@ void ui_light(light_t *l) { ui_float_("Shadow Bias", &l->shadow_bias, 0.00005); ui_float_("Normal Bias", &l->normal_bias, 0.00005); ui_float_("Shadow Softness", &l->shadow_softness, 0.5); + ui_float_("Penumbra Size", &l->penumbra_size, 0.5f); ui_float_("Min Variance", &l->min_variance, 0.00005); ui_float_("Variance Transition", &l->variance_transition, 0.0005); } diff --git a/engine/split/v4k_render.c b/engine/split/v4k_render.c index c66a56f..53ef353 100644 --- a/engine/split/v4k_render.c +++ b/engine/split/v4k_render.c @@ -1487,6 +1487,7 @@ light_t light() { l.shadow_bias = 0.15f; l.normal_bias = 0.05f; l.shadow_softness = 7.0f; + l.penumbra_size = 0.0f; l.min_variance = 0.00002f; l.variance_transition = 0.2f; return l; @@ -1570,6 +1571,7 @@ void light_update(unsigned num_lights, light_t *lv) { shader_float(va("u_lights[%d].shadow_bias", i), lv[i].shadow_bias); shader_float(va("u_lights[%d].normal_bias", i), lv[i].normal_bias); shader_float(va("u_lights[%d].shadow_softness", i), lv[i].shadow_softness); + shader_float(va("u_lights[%d].penumbra_size", i), lv[i].penumbra_size); shader_float(va("u_lights[%d].min_variance", i), lv[i].min_variance); shader_float(va("u_lights[%d].variance_transition", i), lv[i].variance_transition); shader_bool(va("u_lights[%d].processed_shadows", i), lv[i].processed_shadows); @@ -1598,6 +1600,7 @@ void ui_light(light_t *l) { ui_float_("Shadow Bias", &l->shadow_bias, 0.00005); ui_float_("Normal Bias", &l->normal_bias, 0.00005); ui_float_("Shadow Softness", &l->shadow_softness, 0.5); + ui_float_("Penumbra Size", &l->penumbra_size, 0.5f); ui_float_("Min Variance", &l->min_variance, 0.00005); ui_float_("Variance Transition", &l->variance_transition, 0.0005); } diff --git a/engine/split/v4k_render.h b/engine/split/v4k_render.h index 74f8546..2bf9ff4 100644 --- a/engine/split/v4k_render.h +++ b/engine/split/v4k_render.h @@ -324,6 +324,7 @@ typedef struct light_t { float shadow_bias; //< CSM float normal_bias; //< CSM float shadow_softness; + float penumbra_size; // internals bool cached; //< used by scene to invalidate cached light data diff --git a/engine/v4k.c b/engine/v4k.c index 06077d7..5a7f5e4 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -18341,6 +18341,7 @@ light_t light() { l.shadow_bias = 0.15f; l.normal_bias = 0.05f; l.shadow_softness = 7.0f; + l.penumbra_size = 0.0f; l.min_variance = 0.00002f; l.variance_transition = 0.2f; return l; @@ -18424,6 +18425,7 @@ void light_update(unsigned num_lights, light_t *lv) { shader_float(va("u_lights[%d].shadow_bias", i), lv[i].shadow_bias); shader_float(va("u_lights[%d].normal_bias", i), lv[i].normal_bias); shader_float(va("u_lights[%d].shadow_softness", i), lv[i].shadow_softness); + shader_float(va("u_lights[%d].penumbra_size", i), lv[i].penumbra_size); shader_float(va("u_lights[%d].min_variance", i), lv[i].min_variance); shader_float(va("u_lights[%d].variance_transition", i), lv[i].variance_transition); shader_bool(va("u_lights[%d].processed_shadows", i), lv[i].processed_shadows); @@ -18452,6 +18454,7 @@ void ui_light(light_t *l) { ui_float_("Shadow Bias", &l->shadow_bias, 0.00005); ui_float_("Normal Bias", &l->normal_bias, 0.00005); ui_float_("Shadow Softness", &l->shadow_softness, 0.5); + ui_float_("Penumbra Size", &l->penumbra_size, 0.5f); ui_float_("Min Variance", &l->min_variance, 0.00005); ui_float_("Variance Transition", &l->variance_transition, 0.0005); } diff --git a/engine/v4k.h b/engine/v4k.h index 6bf61c2..f3da9fe 100644 --- a/engine/v4k.h +++ b/engine/v4k.h @@ -3359,6 +3359,7 @@ typedef struct light_t { float shadow_bias; //< CSM float normal_bias; //< CSM float shadow_softness; + float penumbra_size; // internals bool cached; //< used by scene to invalidate cached light data