[vulkan] Compute correct matrices for spots and points

Directional lights don't get correct matrices yet as I need to study the
math involved for cascaded shadow maps (and id maps don't have
directional lights).

Getting spotlights working correctly was insanely frustrating: I just
couldn't get the entities into the view of the spotlight with any
sensible combination of inverses and the z_up matrix. It turned out it
was all due to an incorrect reference vector: it was +Z instead of +X.
This commit is contained in:
Bill Currie 2023-07-30 11:59:47 +09:00
parent ff27da4a05
commit 14c94711fd

View file

@ -886,17 +886,7 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx)
free (lctx); free (lctx);
} }
static vec4f_t ref_direction = { 0, 0, 1, 0 }; static vec4f_t ref_direction = { 1, 0, 0, 0 };
// Quake's world is z-up, x-forward, y-left, but Vulkan's world is
// z-forward, x-right, y-down.
//FIXME copy of z_up in vulkan_matrices.c
static mat4f_t z_up = {
{ 0, 0, 1, 0},
{-1, 0, 0, 0},
{ 0,-1, 0, 0},
{ 0, 0, 0, 1},
};
static void static void
create_light_matrices (lightingctx_t *lctx) create_light_matrices (lightingctx_t *lctx)
@ -904,18 +894,28 @@ create_light_matrices (lightingctx_t *lctx)
auto reg = lctx->scene->reg; auto reg = lctx->scene->reg;
auto light_pool = &reg->comp_pools[scene_light]; auto light_pool = &reg->comp_pools[scene_light];
auto light_data = (light_t *) light_pool->data; auto light_data = (light_t *) light_pool->data;
DARRAY_RESIZE (&lctx->light_mats, light_pool->count); uint16_t mat_count = 0;
for (size_t i = 0; i < light_pool->count; i++) { for (uint32_t i = 0; i < light_pool->count; i++) {
entity_t ent = { .reg = reg, .id = light_pool->dense[i] };
uint32_t id = get_lightid (ent);
auto r = &lctx->light_renderers.a[id];
r->matrix_base = mat_count;
mat_count += r->numLayers;
}
DARRAY_RESIZE (&lctx->light_mats, mat_count);
for (uint32_t i = 0; i < light_pool->count; i++) {
light_t *light = &light_data[i]; light_t *light = &light_data[i];
entity_t ent = { .reg = reg, .id = light_pool->dense[i] }; entity_t ent = { .reg = reg, .id = light_pool->dense[i] };
uint32_t id = get_lightid (ent); uint32_t id = get_lightid (ent);
int mode = lctx->light_renderers.a[id].mode; auto r = &lctx->light_renderers.a[id];
auto lm = &lctx->light_mats.a[r->matrix_base];
mat4f_t view; mat4f_t view;
mat4f_t proj; mat4f_t proj;
switch (mode) { switch (r->mode) {
default: default:
case ST_NONE: case ST_NONE:
continue;
case ST_CUBE: case ST_CUBE:
mat4fidentity (view); mat4fidentity (view);
break; break;
@ -927,25 +927,38 @@ create_light_matrices (lightingctx_t *lctx)
mat4fquat (view, qrotf (dir, ref_direction)); mat4fquat (view, qrotf (dir, ref_direction));
break; break;
} }
VectorNegate (light->position, view[3]); vec4f_t pos = -light->position;
pos[3] = 1;
view[3] = mvmulf (view, pos);
switch (mode) { switch (r->mode) {
case ST_NONE: case ST_NONE:
mat4fidentity (proj); continue;
break;
case ST_CUBE: case ST_CUBE:
QFV_PerspectiveTan (proj, 1, 1); QFV_PerspectiveTan (proj, 1, 1);
for (int j = 0; j < 6; j++) {
mat4f_t side_view;
mat4f_t rotinv;
mat4ftranspose (rotinv, qfv_box_rotations[j]);
mmulf (side_view, rotinv, view);
mmulf (side_view, qfv_z_up, side_view);
mmulf (lm[j], proj, side_view);
}
break; break;
case ST_CASCADE: case ST_CASCADE:
// dependent on view fustrum and cascade level // dependent on view fustrum and cascade level
mat4fidentity (proj); mat4fidentity (proj);
mmulf (view, qfv_z_up, view);
for (int j = 0; j < 4; j++) {
mmulf (lm[j], proj, view);
}
break; break;
case ST_PLANE: case ST_PLANE:
QFV_PerspectiveCos (proj, -light->direction[3]); QFV_PerspectiveCos (proj, -light->direction[3]);
mmulf (view, qfv_z_up, view);
mmulf (lm[0], proj, view);
break; break;
} }
mmulf (view, z_up, view);
mmulf (lctx->light_mats.a[id], proj, view);
} }
} }