From 70b60456a8c09ad17e3fc5d157febb32feeccc2e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Aug 2023 02:33:19 +0900 Subject: [PATCH] [vulkan] Implement direction shadow lighting Finally, even suns cast shadows :) --- libs/video/renderer/vulkan/rp_main_def.plist | 1 + .../renderer/vulkan/shader/alias_gbuf.frag | 2 +- .../renderer/vulkan/shader/bsp_gbuf.frag | 2 +- libs/video/renderer/vulkan/shader/iqm.frag | 2 +- libs/video/renderer/vulkan/shader/lighting.h | 5 +++++ .../vulkan/shader/lighting_cascade.frag | 13 ++++++++++-- .../renderer/vulkan/shader/lighting_cube.frag | 6 +++--- .../renderer/vulkan/shader/lighting_main.finc | 8 ++----- .../renderer/vulkan/shader/lighting_none.frag | 2 +- .../vulkan/shader/lighting_plane.frag | 4 ++-- .../renderer/vulkan/shader/sprite_gbuf.frag | 2 +- libs/video/renderer/vulkan/vulkan_lighting.c | 21 ++++++++++++++----- 12 files changed, 45 insertions(+), 23 deletions(-) diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index f3875ce2f..c472411e3 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -697,6 +697,7 @@ properties = { lighting_attach, lighting_shadow); pushConstants = { fragment = { + CascadeDepths = vec4; queue = uint; }; }; diff --git a/libs/video/renderer/vulkan/shader/alias_gbuf.frag b/libs/video/renderer/vulkan/shader/alias_gbuf.frag index 446219ad7..d0316db30 100644 --- a/libs/video/renderer/vulkan/shader/alias_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/alias_gbuf.frag @@ -34,5 +34,5 @@ main (void) frag_color = c; frag_emission = e; frag_normal = vec4(normalize(normal), 1); - frag_position = position; + frag_position = vec4 (position.xyz, gl_FragCoord.z); } diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag index eeaff7db7..045e3021d 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag @@ -43,5 +43,5 @@ main (void) frag_color = c;//fogBlend (c); frag_emission = e; frag_normal = vec4 (normal, 0); - frag_position = position; + frag_position = vec4 (position.xyz, gl_FragCoord.z); } diff --git a/libs/video/renderer/vulkan/shader/iqm.frag b/libs/video/renderer/vulkan/shader/iqm.frag index db8e781e8..953dc5855 100644 --- a/libs/video/renderer/vulkan/shader/iqm.frag +++ b/libs/video/renderer/vulkan/shader/iqm.frag @@ -44,5 +44,5 @@ main (void) frag_color = c; frag_emission = vec4(0,0,0,1);//e; frag_normal = vec4(normal,1);//vec4(tbn * n, 1); - frag_position = position; + frag_position = vec4 (position.xyz, gl_FragCoord.z); } diff --git a/libs/video/renderer/vulkan/shader/lighting.h b/libs/video/renderer/vulkan/shader/lighting.h index 6c537a707..2c244bd9b 100644 --- a/libs/video/renderer/vulkan/shader/lighting.h +++ b/libs/video/renderer/vulkan/shader/lighting.h @@ -33,3 +33,8 @@ layout (set = 1, binding = 3) buffer Style { layout (set = 1, binding = 4) buffer LightEntIds { uint light_entids[]; }; + +layout (push_constant) uniform PushConstants { + vec4 CascadeDepths; + uint queue; +}; diff --git a/libs/video/renderer/vulkan/shader/lighting_cascade.frag b/libs/video/renderer/vulkan/shader/lighting_cascade.frag index 3e16311cc..2d192674e 100644 --- a/libs/video/renderer/vulkan/shader/lighting_cascade.frag +++ b/libs/video/renderer/vulkan/shader/lighting_cascade.frag @@ -5,9 +5,18 @@ layout (set = 3, binding = 0) uniform sampler2DArrayShadow shadow_map[32]; float -shadow (uint map_id, uint layer, uint mat_id, vec3 pos, vec3 lpos) +shadow (uint map_id, uint layer, uint mat_id, vec4 pos, vec3 lpos) { - return 1; + float fd = pos.w; + uint ind = fd > CascadeDepths[1] + ? fd > CascadeDepths[0] ? 0 : 1 + : fd > CascadeDepths[2] ? 2 : 3; + + vec4 p = shadow_mats[mat_id + ind] * vec4 (pos.xyz, 1); + p = p / p.w; + float depth = p.z; + vec2 uv = (p.xy + vec2(1)) / 2; + return texture (shadow_map[map_id], vec4 (uv, layer + ind, depth)); } #include "lighting_main.finc" diff --git a/libs/video/renderer/vulkan/shader/lighting_cube.frag b/libs/video/renderer/vulkan/shader/lighting_cube.frag index ffb020919..a117bb3e6 100644 --- a/libs/video/renderer/vulkan/shader/lighting_cube.frag +++ b/libs/video/renderer/vulkan/shader/lighting_cube.frag @@ -5,9 +5,9 @@ layout (set = 3, binding = 0) uniform samplerCubeArrayShadow shadow_map[32]; float -shadow (uint map_id, uint layer, uint mat_id, vec3 pos, vec3 lpos) +shadow (uint map_id, uint layer, uint mat_id, vec4 pos, vec3 lpos) { - vec3 dir = pos - lpos; + vec3 dir = pos.xyz - lpos; vec3 adir = abs(dir); adir = max (adir.yzx, adir.zxy); uint ind = dir.x <= -adir.x ? 5 @@ -16,7 +16,7 @@ shadow (uint map_id, uint layer, uint mat_id, vec3 pos, vec3 lpos) : dir.y >= adir.y ? 1 : dir.z <= -adir.z ? 3 : dir.z >= adir.z ? 2 : 0; - vec4 p = shadow_mats[mat_id + ind] * vec4 (pos, 1); + vec4 p = shadow_mats[mat_id + ind] * vec4 (pos.xyz, 1); p = p / p.w; float depth = p.z; // convert from the quake frame to the cubemap frame diff --git a/libs/video/renderer/vulkan/shader/lighting_main.finc b/libs/video/renderer/vulkan/shader/lighting_main.finc index 5e042e4ae..c8e790c79 100644 --- a/libs/video/renderer/vulkan/shader/lighting_main.finc +++ b/libs/video/renderer/vulkan/shader/lighting_main.finc @@ -5,10 +5,6 @@ layout (input_attachment_index = 3, set = 2, binding = 3) uniform subpassInput p layout (location = 0) out vec4 frag_color; -layout (push_constant) uniform PushConstants { - uint queue; -}; - float spot_cone (LightData light, vec3 incoming) { @@ -31,7 +27,7 @@ main (void) vec3 c = subpassLoad (color).rgb; vec3 e = subpassLoad (emission).rgb; vec3 n = subpassLoad (normal).rgb; - vec3 p = subpassLoad (position).rgb; + vec4 p = subpassLoad (position); vec3 light = vec3 (0); uint start = bitfieldExtract (queue, 0, 16); @@ -40,7 +36,7 @@ main (void) for (uint i = start; i < end; i++) { uint id = lightIds[i]; LightData l = lights[id]; - vec3 dir = l.position.xyz - l.position.w * p; + vec3 dir = l.position.xyz - l.position.w * p.xyz; float r2 = dot (dir, dir); vec4 a = l.attenuation; diff --git a/libs/video/renderer/vulkan/shader/lighting_none.frag b/libs/video/renderer/vulkan/shader/lighting_none.frag index a683b5758..d43bccb4f 100644 --- a/libs/video/renderer/vulkan/shader/lighting_none.frag +++ b/libs/video/renderer/vulkan/shader/lighting_none.frag @@ -3,7 +3,7 @@ #include "lighting.h" float -shadow (uint mapid, uint layer, uint mat_id, vec3 pos, vec3 lpos) +shadow (uint mapid, uint layer, uint mat_id, vec4 pos, vec3 lpos) { return 1; } diff --git a/libs/video/renderer/vulkan/shader/lighting_plane.frag b/libs/video/renderer/vulkan/shader/lighting_plane.frag index 68742a940..db20be866 100644 --- a/libs/video/renderer/vulkan/shader/lighting_plane.frag +++ b/libs/video/renderer/vulkan/shader/lighting_plane.frag @@ -5,9 +5,9 @@ layout (set = 3, binding = 0) uniform sampler2DArrayShadow shadow_map[32]; float -shadow (uint map_id, uint layer, uint mat_id, vec3 pos, vec3 lpos) +shadow (uint map_id, uint layer, uint mat_id, vec4 pos, vec3 lpos) { - vec4 p = shadow_mats[mat_id] * vec4 (pos, 1); + vec4 p = shadow_mats[mat_id] * vec4 (pos.xyz, 1); p = p / p.w; float depth = p.z; vec2 uv = (p.xy + vec2(1)) / 2; diff --git a/libs/video/renderer/vulkan/shader/sprite_gbuf.frag b/libs/video/renderer/vulkan/shader/sprite_gbuf.frag index 29d9b65c9..17935aedb 100644 --- a/libs/video/renderer/vulkan/shader/sprite_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/sprite_gbuf.frag @@ -33,5 +33,5 @@ main (void) frag_color = vec4(0,0,0,1); frag_emission = pix; frag_normal = vec4(normal, 1); - frag_position = position; + frag_position = vec4 (position.xyz, gl_FragCoord.z); } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index bce54f6d7..a9bd36c59 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -169,8 +169,14 @@ lighting_setup_shadow (const exprval_t **params, exprval_t *result, auto pass = Vulkan_Bsp_GetPass (ctx, QFV_bspShadow); auto brush = pass->brush; - lctx->world_mins = loadvec3f (brush->submodels[0].mins); - lctx->world_maxs = loadvec3f (brush->submodels[0].maxs); + if (brush->submodels) { + lctx->world_mins = loadvec3f (brush->submodels[0].mins); + lctx->world_maxs = loadvec3f (brush->submodels[0].maxs); + } else { + // FIXME better bounds + lctx->world_mins = (vec4f_t) { -512, -512, -512, 0 }; + lctx->world_maxs = (vec4f_t) { 512, 512, 512, 0 }; + } set_t leafs = SET_STATIC_INIT (brush->modleafs, alloca); set_empty (&leafs); @@ -760,10 +766,15 @@ lighting_draw_lights (const exprval_t **params, exprval_t *result, return; } - qfv_push_constants_t push_constants[] = { - { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (queue), &queue }, + //FIXME dup of z_range (sort of) + vec4f_t depths = { + r_nearclip / 32, r_nearclip / 256, r_nearclip / 1024, 0, }; - QFV_PushConstants (device, cmd, layout, 1, push_constants); + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (depths), &depths }, + { VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(depths), sizeof(queue), &queue }, + }; + QFV_PushConstants (device, cmd, layout, 2, push_constants); dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); }