mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-15 22:01:01 +00:00
[vulkan] Move light radius calcs to the CPU
No point in calculating them for every vertex, especially when I forgot to update the calculations for the entid vertex shader.
This commit is contained in:
parent
00ecb7d71a
commit
f08b8dc3c7
5 changed files with 74 additions and 23 deletions
|
@ -94,6 +94,7 @@ typedef struct lightingframe_s {
|
|||
VkBuffer render_buffer;
|
||||
VkBuffer style_buffer;
|
||||
VkBuffer id_buffer;
|
||||
VkBuffer radius_buffer;
|
||||
VkBuffer entid_buffer;
|
||||
light_queue_t light_queue[4];
|
||||
|
||||
|
|
|
@ -670,11 +670,13 @@ properties = {
|
|||
vertexInput_splat = {
|
||||
bindings = (
|
||||
{ binding = 0; stride = "4"; inputRate = instance; },
|
||||
{ binding = 1; stride = "3 * 4"; inputRate = vertex; },
|
||||
{ binding = 1; stride = "4"; inputRate = instance; },
|
||||
{ binding = 2; stride = "3 * 4"; inputRate = vertex; },
|
||||
);
|
||||
attributes = (
|
||||
{ location = 0; binding = 0; format = r32_uint; offset = 0; },
|
||||
{ location = 1; binding = 1; format = r32g32b32_sfloat; offset = 0; },
|
||||
{ location = 1; binding = 1; format = r32_sfloat; offset = 0; },
|
||||
{ location = 2; binding = 2; format = r32g32b32_sfloat; offset = 0; },
|
||||
);
|
||||
};
|
||||
vertexInput_flat = {
|
||||
|
|
|
@ -9,7 +9,8 @@ layout (set = 0, binding = 0) uniform
|
|||
#include "lighting.h"
|
||||
|
||||
layout (location = 0) in uint light_index;
|
||||
layout (location = 1) in vec3 splat_vert;
|
||||
layout (location = 1) in float light_radius;
|
||||
layout (location = 2) in vec3 splat_vert;
|
||||
layout (location = 0) out uint light_index_out;
|
||||
|
||||
vec4 // assumes a and b are unit vectors
|
||||
|
@ -33,7 +34,7 @@ void
|
|||
main (void)
|
||||
{
|
||||
LightData l = lights[light_index];
|
||||
float sz = l.attenuation.w > 0 ? 1 / l.attenuation.w : sqrt(abs(l.color.w));
|
||||
float sz = light_radius;
|
||||
float c = l.direction.w;
|
||||
float sxy = sz * (c < 0 ? (sqrt (1 - c*c) / -c) : 1);
|
||||
vec3 scale = vec3 (sxy, sxy, sz);
|
||||
|
|
|
@ -9,7 +9,8 @@ layout (set = 0, binding = 0) uniform
|
|||
#include "lighting.h"
|
||||
|
||||
layout (location = 0) in uint light_index;
|
||||
layout (location = 1) in vec3 splat_vert;
|
||||
layout (location = 1) in float light_radius;
|
||||
layout (location = 2) in vec3 splat_vert;
|
||||
layout (location = 0) out uint light_index_out;
|
||||
|
||||
vec4 // assumes a and b are unit vectors
|
||||
|
@ -33,10 +34,7 @@ void
|
|||
main (void)
|
||||
{
|
||||
LightData l = lights[light_index];
|
||||
float sz = l.attenuation.w > 0 ? 1 / l.attenuation.w
|
||||
: l.attenuation.x > 0 ? sqrt(abs(l.color.w/l.attenuation.x))
|
||||
: l.attenuation.y > 0 ? abs(l.color.w/l.attenuation.y)
|
||||
: sqrt(abs(l.color.w));
|
||||
float sz = light_radius;
|
||||
float c = l.direction.w;
|
||||
float sxy = sz * (c < 0 ? (sqrt (1 - c*c) / -c) : 1);
|
||||
vec3 scale = vec3 (sxy, sxy, sz);
|
||||
|
|
|
@ -588,6 +588,16 @@ transition_shadow_targets (lightingframe_t *lframe, vulkan_ctx_t *ctx)
|
|||
QFV_AppendCmdBuffer (ctx, cmd);
|
||||
}
|
||||
|
||||
static float
|
||||
light_radius (const light_t *l)
|
||||
{
|
||||
return l->attenuation[3] > 0 ? 1 / l->attenuation[3]
|
||||
: l->attenuation[0] > 0 ? sqrt(abs(l->color[3]/l->attenuation[0]))
|
||||
: l->attenuation[1] > 0 ? abs(l->color[3]/l->attenuation[1])
|
||||
// FIXME ambient lights. not right, but at least it will render
|
||||
: sqrt(abs(l->color[3]));
|
||||
}
|
||||
|
||||
static void
|
||||
lighting_update_lights (const exprval_t **params, exprval_t *result,
|
||||
exprctx_t *ectx)
|
||||
|
@ -607,6 +617,7 @@ lighting_update_lights (const exprval_t **params, exprval_t *result,
|
|||
auto bb = &bufferBarriers[qfv_BB_TransferWrite_to_UniformRead];
|
||||
|
||||
uint32_t light_ids[ST_COUNT][MaxLights];
|
||||
float light_radii[ST_COUNT][MaxLights];
|
||||
uint32_t entids[ST_COUNT][MaxLights];
|
||||
|
||||
uint32_t light_count = 0;
|
||||
|
@ -645,7 +656,9 @@ lighting_update_lights (const exprval_t **params, exprval_t *result,
|
|||
lframe->stage_queue[r->stage_index].count += r->numLayers;
|
||||
|
||||
int mode = r->mode;
|
||||
auto light = get_light (ent.id, ent.reg);
|
||||
light_ids[mode][queue[mode].count] = id;
|
||||
light_radii[mode][queue[mode].count] = light_radius (light);
|
||||
entids[mode][queue[mode].count] = ent.id;
|
||||
queue[mode].count++;
|
||||
}
|
||||
|
@ -672,6 +685,8 @@ lighting_update_lights (const exprval_t **params, exprval_t *result,
|
|||
if (light_count) {
|
||||
// light ids
|
||||
packet_size += sizeof (uint32_t[light_count]);
|
||||
// light radii
|
||||
packet_size += sizeof (float[light_count]);
|
||||
// ent ids
|
||||
packet_size += sizeof (uint32_t[light_count]);
|
||||
}
|
||||
|
@ -738,22 +753,26 @@ lighting_update_lights (const exprval_t **params, exprval_t *result,
|
|||
};
|
||||
packet_data += light_scatter.length;
|
||||
for (int i = 0; i < ndlight; i++) {
|
||||
light_t light = {
|
||||
.color = {
|
||||
VectorExpand (dynamic_lights[i]->color),
|
||||
// dynamic lights seem a tad faint, so 16x map lights
|
||||
dynamic_lights[i]->radius / 16,
|
||||
},
|
||||
// dlights are local point sources
|
||||
.position = { VectorExpand (dynamic_lights[i]->origin), 1 },
|
||||
// full sphere, normal light (not ambient)
|
||||
.direction = { 0, 0, 1, 1 },
|
||||
.attenuation = { 0, 0, 1, 1/dynamic_lights[i]->radius },
|
||||
};
|
||||
uint32_t id = lctx->dynamic_base + i;
|
||||
set_lightid (dynamic_light_entities[i], lctx->scene->reg, id);
|
||||
light_ids[ST_CUBE][queue[ST_CUBE].count] = id;
|
||||
light_radii[ST_CUBE][queue[ST_CUBE].count] = light_radius (&light);
|
||||
entids[ST_CUBE][queue[ST_CUBE].count] = dynamic_light_entities[i];
|
||||
queue[ST_CUBE].count++;
|
||||
|
||||
VectorCopy (dynamic_lights[i]->color, lights[i].color);
|
||||
// dynamic lights seem a tad faint, so 16x map lights
|
||||
lights[i].color[3] = dynamic_lights[i]->radius / 16;
|
||||
VectorCopy (dynamic_lights[i]->origin, lights[i].position);
|
||||
// dlights are local point sources
|
||||
lights[i].position[3] = 1;
|
||||
lights[i].attenuation =
|
||||
(vec4f_t) { 0, 0, 1, 1/dynamic_lights[i]->radius };
|
||||
// full sphere, normal light (not ambient)
|
||||
lights[i].direction = (vec4f_t) { 0, 0, 1, 1 };
|
||||
lights[i] = light;
|
||||
}
|
||||
QFV_PacketScatterBuffer (packet, lframe->light_buffer,
|
||||
1, &light_scatter, bb);
|
||||
|
@ -786,6 +805,7 @@ lighting_update_lights (const exprval_t **params, exprval_t *result,
|
|||
for (int i = 1; i < ST_COUNT; i++) {
|
||||
queue[i].start = queue[i - 1].start + queue[i - 1].count;
|
||||
}
|
||||
|
||||
auto lids = (uint32_t *) packet_data;
|
||||
qfv_scatter_t lid_scatter = {
|
||||
.srcOffset = packet_data - packet_start,
|
||||
|
@ -801,6 +821,21 @@ lighting_update_lights (const exprval_t **params, exprval_t *result,
|
|||
1, &lid_scatter,
|
||||
&bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]);
|
||||
|
||||
auto lradii = (float *) packet_data;
|
||||
qfv_scatter_t lradius_scatter = {
|
||||
.srcOffset = packet_data - packet_start,
|
||||
.dstOffset = 0,
|
||||
.length = sizeof (float[light_count]),
|
||||
};
|
||||
packet_data += lradius_scatter.length;
|
||||
for (int i = 0; i < ST_COUNT; i++) {
|
||||
memcpy (lradii + queue[i].start, light_radii[i],
|
||||
sizeof (float[queue[i].count]));
|
||||
}
|
||||
QFV_PacketScatterBuffer (packet, lframe->radius_buffer,
|
||||
1, &lradius_scatter,
|
||||
&bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]);
|
||||
|
||||
auto eids = (uint32_t *) packet_data;
|
||||
qfv_scatter_t eid_scatter = {
|
||||
.srcOffset = packet_data - packet_start,
|
||||
|
@ -937,10 +972,11 @@ lighting_bind_descriptors (const exprval_t **params, exprval_t *result,
|
|||
|
||||
VkBuffer buffers[] = {
|
||||
lframe->id_buffer,
|
||||
lframe->radius_buffer,
|
||||
lctx->splat_verts,
|
||||
};
|
||||
VkDeviceSize offsets[] = { 0, 0 };
|
||||
dfunc->vkCmdBindVertexBuffers (cmd, 0, 2, buffers, offsets);
|
||||
VkDeviceSize offsets[] = { 0, 0, 0 };
|
||||
dfunc->vkCmdBindVertexBuffers (cmd, 0, 3, buffers, offsets);
|
||||
dfunc->vkCmdBindIndexBuffer (cmd, lctx->splat_inds, 0,
|
||||
VK_INDEX_TYPE_UINT32);
|
||||
} else {
|
||||
|
@ -1401,6 +1437,8 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
|
|||
+ sizeof (qfv_resobj_t[frames])
|
||||
// light ids
|
||||
+ sizeof (qfv_resobj_t[frames])
|
||||
// light radii
|
||||
+ sizeof (qfv_resobj_t[frames])
|
||||
// light data
|
||||
+ sizeof (qfv_resobj_t[frames])
|
||||
// light render
|
||||
|
@ -1413,7 +1451,7 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
|
|||
.name = "lights",
|
||||
.va_ctx = ctx->va_ctx,
|
||||
.memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
.num_objects = 2 + 3 + 7 * frames,
|
||||
.num_objects = 2 + 3 + 8 * frames,
|
||||
.objects = (qfv_resobj_t *) &lctx->light_resources[1],
|
||||
};
|
||||
auto splat_verts = lctx->light_resources->objects;
|
||||
|
@ -1424,7 +1462,8 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
|
|||
auto light_mats = &default_view_2d[1];
|
||||
auto light_mat_ids = &light_mats[frames];
|
||||
auto light_ids = &light_mat_ids[frames];
|
||||
auto light_data = &light_ids[frames];
|
||||
auto light_radii = &light_ids[frames];
|
||||
auto light_data = &light_radii[frames];
|
||||
auto light_render = &light_data[frames];
|
||||
auto light_styles = &light_render[frames];
|
||||
auto light_entids = &light_styles[frames];
|
||||
|
@ -1510,6 +1549,15 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
|
|||
| VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
},
|
||||
};
|
||||
light_radii[i] = (qfv_resobj_t) {
|
||||
.name = va (ctx->va_ctx, "radii:%zd", i),
|
||||
.type = qfv_res_buffer,
|
||||
.buffer = {
|
||||
.size = MaxLights * sizeof (float),
|
||||
.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
},
|
||||
};
|
||||
light_data[i] = (qfv_resobj_t) {
|
||||
.name = va (ctx->va_ctx, "lights:%zd", i),
|
||||
.type = qfv_res_buffer,
|
||||
|
@ -1591,6 +1639,7 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx)
|
|||
.render_buffer = light_render[i].buffer.buffer,
|
||||
.style_buffer = light_styles[i].buffer.buffer,
|
||||
.id_buffer = light_ids[i].buffer.buffer,
|
||||
.radius_buffer = light_radii[i].buffer.buffer,
|
||||
.entid_buffer = light_entids[i].buffer.buffer,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue