From 2fbe44a72eb0c72d93bfe3a7a0c76165008629bf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 3 Aug 2023 00:05:41 +0900 Subject: [PATCH] [vulkan] Get point light shadows working Other than the rather bad shadow acne, this is actually quake itself working nicely. Still need to get directional lights working for community maps, and all sorts of other little things (hide view model, show player, fix brush backfaces, etc). --- .../vulkan/shader/lighting_cascade.frag | 2 +- .../renderer/vulkan/shader/lighting_cube.frag | 21 +++++++++++++++---- .../renderer/vulkan/shader/lighting_main.finc | 2 +- .../renderer/vulkan/shader/lighting_none.frag | 2 +- .../vulkan/shader/lighting_plane.frag | 2 +- libs/video/renderer/vulkan/vulkan_lighting.c | 6 ++++-- 6 files changed, 25 insertions(+), 10 deletions(-) diff --git a/libs/video/renderer/vulkan/shader/lighting_cascade.frag b/libs/video/renderer/vulkan/shader/lighting_cascade.frag index 7f453a0ed..bc9118645 100644 --- a/libs/video/renderer/vulkan/shader/lighting_cascade.frag +++ b/libs/video/renderer/vulkan/shader/lighting_cascade.frag @@ -4,7 +4,7 @@ layout (set = 3, binding = 0) uniform sampler2DArrayShadow shadow_map[32]; float -shadow (uint map_id, uint layer, uint mat_id, vec3 pos) +shadow (uint map_id, uint layer, uint mat_id, vec3 pos, vec3 lpos) { return 1; } diff --git a/libs/video/renderer/vulkan/shader/lighting_cube.frag b/libs/video/renderer/vulkan/shader/lighting_cube.frag index 05fab8045..295efc369 100644 --- a/libs/video/renderer/vulkan/shader/lighting_cube.frag +++ b/libs/video/renderer/vulkan/shader/lighting_cube.frag @@ -7,11 +7,24 @@ layout (set = 0, binding = 0) buffer ShadowMatrices { layout (set = 3, binding = 0) uniform samplerCubeArrayShadow shadow_map[32]; float -shadow (uint map_id, uint layer, uint mat_id, vec3 pos) +shadow (uint map_id, uint layer, uint mat_id, vec3 pos, vec3 lpos) { - vec4 p = shadow_mats[mat_id] * vec4 (pos, 1); - float depth = (p / p.w).z; - return texture (shadow_map[map_id], vec4 (p.xyz, layer), depth); + vec3 dir = pos - lpos; + vec3 adir = abs(dir); + adir = max (adir.yzx, adir.zxy); + uint ind = dir.x <= -adir.x ? 5 + : dir.x >= adir.x ? 4 + : dir.y <= -adir.y ? 0 + : 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); + p = p / (p.w - 0.5); //FIXME hard-coded bias + float depth = p.z; + dir = mat3(vec3( 0, 0, 1), + vec3(-1, 0, 0), + vec3( 0, 1, 0)) * dir; + return texture (shadow_map[map_id], vec4 (dir, layer), depth); } #include "lighting_main.finc" diff --git a/libs/video/renderer/vulkan/shader/lighting_main.finc b/libs/video/renderer/vulkan/shader/lighting_main.finc index ceb5bd151..075efc199 100644 --- a/libs/video/renderer/vulkan/shader/lighting_main.finc +++ b/libs/video/renderer/vulkan/shader/lighting_main.finc @@ -54,7 +54,7 @@ main (void) uint map_id = bitfieldExtract (id_data, 13, 5); uint layer = bitfieldExtract (id_data, 18, 11); - I *= shadow (map_id, layer, mat_id, p); + I *= shadow (map_id, layer, mat_id, p, l.position.xyz); float namb = dot(l.direction.xyz, l.direction.xyz); I *= spot_cone (l, incoming) * diffuse (incoming, n); diff --git a/libs/video/renderer/vulkan/shader/lighting_none.frag b/libs/video/renderer/vulkan/shader/lighting_none.frag index 12f908d7e..2b61473fa 100644 --- a/libs/video/renderer/vulkan/shader/lighting_none.frag +++ b/libs/video/renderer/vulkan/shader/lighting_none.frag @@ -2,7 +2,7 @@ #extension GL_GOOGLE_include_directive : enable float -shadow (uint mapid, uint layer, uint mat_id, vec3 pos) +shadow (uint mapid, uint layer, uint mat_id, vec3 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 0c9ea196c..c01bd66d2 100644 --- a/libs/video/renderer/vulkan/shader/lighting_plane.frag +++ b/libs/video/renderer/vulkan/shader/lighting_plane.frag @@ -7,7 +7,7 @@ layout (set = 0, binding = 0) buffer ShadowMatrices { layout (set = 3, binding = 0) uniform sampler2DArrayShadow shadow_map[32]; float -shadow (uint map_id, uint layer, uint mat_id, vec3 pos) +shadow (uint map_id, uint layer, uint mat_id, vec3 pos, vec3 lpos) { vec4 p = shadow_mats[mat_id] * vec4 (pos, 1); p = p / (p.w - 0.5); //FIXME hard-coded bias diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 62fd1f324..cfcd47ebc 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -349,7 +349,6 @@ lighting_update_lights (const exprval_t **params, exprval_t *result, //.id_data = make_id(r->matrix_id, r->map_index, r->layer, //r->mode), .id_data = 0x80000000, // no style - .style = 11, }; } dlight_offset = sizeof (qfv_light_render_t[lctx->dynamic_base]); @@ -1157,7 +1156,7 @@ create_light_matrices (lightingctx_t *lctx) mmulf (side_view, qfv_z_up, side_view); mmulf (lm[j], proj, side_view); } - r->matrix_id = r->matrix_base + BOX_FRONT; + r->matrix_id = r->matrix_base; break; case ST_CASCADE: // dependent on view fustrum and cascade level @@ -1197,6 +1196,9 @@ static uint32_t make_id (uint32_t matrix_index, uint32_t map_index, uint32_t layer, uint32_t type) { + if (type == ST_CUBE) { + layer /= 6; + } return ((matrix_index & 0x1fff) << 0) | ((map_index & 0x1f) << 13) | ((layer & 0x7ff) << 18)