rtx: point/stop light clusters culling
This commit is contained in:
parent
c1f93ffc54
commit
2ab07547fa
|
@ -34,7 +34,7 @@ layout(set = 0, binding = 2) uniform UBO {
|
||||||
layout (set = 0, binding = 7/*, align=4*/) uniform UBOLights { Lights lights; };
|
layout (set = 0, binding = 7/*, align=4*/) uniform UBOLights { Lights lights; };
|
||||||
|
|
||||||
struct LightCluster {
|
struct LightCluster {
|
||||||
uint8_t num_dlights;
|
uint8_t num_point_lights;
|
||||||
uint8_t num_emissive_surfaces;
|
uint8_t num_emissive_surfaces;
|
||||||
uint8_t point_lights[MAX_VISIBLE_POINT_LIGHTS];
|
uint8_t point_lights[MAX_VISIBLE_POINT_LIGHTS];
|
||||||
uint8_t emissive_surfaces[MAX_VISIBLE_SURFACE_LIGHTS];
|
uint8_t emissive_surfaces[MAX_VISIBLE_SURFACE_LIGHTS];
|
||||||
|
@ -147,13 +147,79 @@ vec3 sampleSurfaceTriangle(vec3 color, vec3 view_dir, MaterialProperties materia
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 computeLighting(vec3 throughput, vec3 view_dir, MaterialProperties material) {
|
vec3 computePointLights(uint cluster_index, vec3 throughput, vec3 view_dir, MaterialProperties material) {
|
||||||
vec3 C = vec3(0.);
|
vec3 C = vec3(0.);
|
||||||
|
|
||||||
|
const uint num_point_lights = uint(light_grid.clusters[cluster_index].num_point_lights);
|
||||||
|
for (uint j = 0; j < num_point_lights; ++j) {
|
||||||
|
const uint i = uint(light_grid.clusters[cluster_index].point_lights[j]);
|
||||||
|
|
||||||
|
vec3 color = lights.point_lights[i].color_stopdot.rgb;
|
||||||
|
color *= throughput * payload.base_color;
|
||||||
|
if (dot(color,color) < color_culling_threshold)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const vec4 origin_r = lights.point_lights[i].origin_r;
|
||||||
|
const float stopdot = lights.point_lights[i].color_stopdot.a;
|
||||||
|
const vec3 dir = lights.point_lights[i].dir_stopdot2.xyz;
|
||||||
|
const float stopdot2 = lights.point_lights[i].dir_stopdot2.a;
|
||||||
|
|
||||||
|
const vec3 light_dir = origin_r.xyz - payload.hit_pos_t.xyz;
|
||||||
|
const vec3 light_dir_norm = normalize(light_dir);
|
||||||
|
const float light_dot = dot(light_dir_norm, payload.normal);
|
||||||
|
if (light_dot < 1e-5)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const float spot_dot = -dot(light_dir_norm, dir);
|
||||||
|
if (spot_dot < stopdot2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float spot_attenuation = 1.f;
|
||||||
|
if (spot_dot < stopdot)
|
||||||
|
spot_attenuation = (spot_dot - stopdot2) / (stopdot - stopdot2);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
const float d2 = dot(light_dir, light_dir);
|
||||||
|
const float r2 = origin_r.w * origin_r.w;
|
||||||
|
const float light_dist = sqrt(d2);
|
||||||
|
const float fdist = 2.f / (r2 + d2 + light_dist * sqrt(d2 + r2));
|
||||||
|
const float pdf = 1.f / (fdist * light_dot * spot_attenuation);
|
||||||
|
#else
|
||||||
|
const float d2 = dot(light_dir, light_dir);
|
||||||
|
//const float r2 = origin_r.w * origin_r.w;
|
||||||
|
const float light_dist = sqrt(d2);
|
||||||
|
//const float fdist = 2.f / (r2 + d2 + light_dist * sqrt(d2 + r2));
|
||||||
|
//const float fdist = 2.f / (r2 + d2 + light_dist * sqrt(d2 + r2));
|
||||||
|
const float fdist = (light_dist > 1.) ? 1.f / d2 : 1.f; // qrad workaround
|
||||||
|
const float pdf = 1.f / (fdist * light_dot * spot_attenuation);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
color /= pdf;
|
||||||
|
// if (dot(color,color) < color_culling_threshold)
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
color *= evalCombinedBRDF(payload.normal, light_dir_norm, view_dir, material);
|
||||||
|
if (dot(color,color) < color_culling_threshold)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (shadowed(payload.hit_pos_t.xyz, light_dir_norm, light_dist + shadow_offset_fudge))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
C += color;
|
||||||
|
} // for all lights
|
||||||
|
|
||||||
|
return C;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 computeLighting(vec3 throughput, vec3 view_dir, MaterialProperties material) {
|
||||||
const ivec3 light_cell = ivec3(floor(payload.hit_pos_t.xyz / LIGHT_GRID_CELL_SIZE)) - light_grid.grid_min;
|
const ivec3 light_cell = ivec3(floor(payload.hit_pos_t.xyz / LIGHT_GRID_CELL_SIZE)) - light_grid.grid_min;
|
||||||
const uint cluster_index = uint(dot(light_cell, ivec3(1, light_grid.grid_size.x, light_grid.grid_size.x * light_grid.grid_size.y)));
|
const uint cluster_index = uint(dot(light_cell, ivec3(1, light_grid.grid_size.x, light_grid.grid_size.x * light_grid.grid_size.y)));
|
||||||
if (any(greaterThanEqual(light_cell, light_grid.grid_size)) || cluster_index >= MAX_LIGHT_CLUSTERS) {
|
|
||||||
C = vec3(1., 0., 0.);
|
if (any(greaterThanEqual(light_cell, light_grid.grid_size)) || cluster_index >= MAX_LIGHT_CLUSTERS)
|
||||||
} else {
|
return throughput * vec3(1., 0., 0.);
|
||||||
|
|
||||||
|
vec3 C = vec3(0.);
|
||||||
|
|
||||||
// const uint cluster_offset = cluster_index * LIGHT_CLUSTER_SIZE + HACK_OFFSET;
|
// const uint cluster_offset = cluster_index * LIGHT_CLUSTER_SIZE + HACK_OFFSET;
|
||||||
// const int num_dlights = int(light_grid.clusters_data[cluster_offset + LIGHT_CLUSTER_NUM_DLIGHTS_OFFSET]);
|
// const int num_dlights = int(light_grid.clusters_data[cluster_offset + LIGHT_CLUSTER_NUM_DLIGHTS_OFFSET]);
|
||||||
// const int num_emissive_surfaces = int(light_grid.clusters_data[cluster_offset + LIGHT_CLUSTER_NUM_EMISSIVE_SURFACES_OFFSET]);
|
// const int num_emissive_surfaces = int(light_grid.clusters_data[cluster_offset + LIGHT_CLUSTER_NUM_EMISSIVE_SURFACES_OFFSET]);
|
||||||
|
@ -207,63 +273,7 @@ vec3 computeLighting(vec3 throughput, vec3 view_dir, MaterialProperties material
|
||||||
C += sampling_light_scale * sampleSurfaceTriangle(throughput * payload.base_color * emissive, view_dir, material, emissive_transform, emissive_transform_normal, triangle_index, ekusok.index_offset, ekusok.vertex_offset);
|
C += sampling_light_scale * sampleSurfaceTriangle(throughput * payload.base_color * emissive, view_dir, material, emissive_transform, emissive_transform_normal, triangle_index, ekusok.index_offset, ekusok.vertex_offset);
|
||||||
} // for all emissive kusochki
|
} // for all emissive kusochki
|
||||||
|
|
||||||
|
C += computePointLights(cluster_index, throughput, view_dir, material);
|
||||||
for (uint i = 0; i < lights.num_point_lights; ++i) {
|
|
||||||
const vec4 origin_r = lights.point_lights[i].origin_r;
|
|
||||||
vec3 color = lights.point_lights[i].color_stopdot.rgb;
|
|
||||||
float stopdot = lights.point_lights[i].color_stopdot.a;
|
|
||||||
vec3 dir = lights.point_lights[i].dir_stopdot2.xyz;
|
|
||||||
float stopdot2 = lights.point_lights[i].dir_stopdot2.a;
|
|
||||||
|
|
||||||
color *= throughput * payload.base_color;
|
|
||||||
// if (dot(color,color) < color_culling_threshold)
|
|
||||||
// continue;
|
|
||||||
|
|
||||||
const vec3 light_dir = origin_r.xyz - payload.hit_pos_t.xyz;
|
|
||||||
const vec3 light_dir_norm = normalize(light_dir);
|
|
||||||
const float light_dot = dot(light_dir_norm, payload.normal);
|
|
||||||
if (light_dot < 1e-5)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const float spot_dot = -dot(light_dir_norm, dir);
|
|
||||||
if (spot_dot < stopdot2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
float spot_attenuation = 1.f;
|
|
||||||
if (spot_dot < stopdot)
|
|
||||||
spot_attenuation = (spot_dot - stopdot2) / (stopdot - stopdot2);
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
const float d2 = dot(light_dir, light_dir);
|
|
||||||
const float r2 = origin_r.w * origin_r.w;
|
|
||||||
const float light_dist = sqrt(d2);
|
|
||||||
const float fdist = 2.f / (r2 + d2 + light_dist * sqrt(d2 + r2));
|
|
||||||
const float pdf = 1.f / (fdist * light_dot * spot_attenuation);
|
|
||||||
#else
|
|
||||||
const float d2 = dot(light_dir, light_dir);
|
|
||||||
//const float r2 = origin_r.w * origin_r.w;
|
|
||||||
const float light_dist = sqrt(d2);
|
|
||||||
//const float fdist = 2.f / (r2 + d2 + light_dist * sqrt(d2 + r2));
|
|
||||||
//const float fdist = 2.f / (r2 + d2 + light_dist * sqrt(d2 + r2));
|
|
||||||
const float fdist = (light_dist > 1.) ? 1.f / d2 : 1.f; // qrad workaround
|
|
||||||
const float pdf = 1.f / (fdist * light_dot * spot_attenuation);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
color /= pdf;
|
|
||||||
// if (dot(color,color) < color_culling_threshold)
|
|
||||||
// continue;
|
|
||||||
|
|
||||||
color *= evalCombinedBRDF(payload.normal, light_dir_norm, view_dir, material);
|
|
||||||
if (dot(color,color) < color_culling_threshold)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (shadowed(payload.hit_pos_t.xyz, light_dir_norm, light_dist + shadow_offset_fudge))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
C += color;
|
|
||||||
} // for all lights
|
|
||||||
}
|
|
||||||
|
|
||||||
return C;
|
return C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,10 @@
|
||||||
// indexed by uint8_t
|
// indexed by uint8_t
|
||||||
#define MAX_POINT_LIGHTS 255
|
#define MAX_POINT_LIGHTS 255
|
||||||
|
|
||||||
|
// indexed by uint8_t
|
||||||
#define MAX_VISIBLE_POINT_LIGHTS 31
|
#define MAX_VISIBLE_POINT_LIGHTS 31
|
||||||
// indexed by uint8_t
|
// indexed by uint8_t
|
||||||
#define MAX_VISIBLE_SURFACE_LIGHTS 255
|
#define MAX_VISIBLE_SURFACE_LIGHTS 255
|
||||||
|
|
||||||
#define MAX_LIGHT_CLUSTERS 262144 //131072 //32768
|
#define MAX_LIGHT_CLUSTERS 262144 //131072 //32768
|
||||||
#define LIGHT_GRID_CELL_SIZE 128
|
#define LIGHT_GRID_CELL_SIZE 128
|
||||||
|
|
|
@ -479,13 +479,13 @@ static struct {
|
||||||
|
|
||||||
} g_lights_bsp = {0};
|
} g_lights_bsp = {0};
|
||||||
|
|
||||||
static void prepareLeafAccum( void ) {
|
static void leafAccumPrepare( void ) {
|
||||||
memset(&g_lights_bsp.accum, 0, sizeof(g_lights_bsp.accum));
|
memset(&g_lights_bsp.accum, 0, sizeof(g_lights_bsp.accum));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LEAF_ADDED_BIT 0x8000000ul
|
#define LEAF_ADDED_BIT 0x8000000ul
|
||||||
|
|
||||||
static qboolean addLeafToAccum( uint16_t leaf_index ) {
|
static qboolean leafAccumAdd( uint16_t leaf_index ) {
|
||||||
// Check whether this leaf was already added
|
// Check whether this leaf was already added
|
||||||
if (g_lights_bsp.accum.leafs[leaf_index] & LEAF_ADDED_BIT)
|
if (g_lights_bsp.accum.leafs[leaf_index] & LEAF_ADDED_BIT)
|
||||||
return false;
|
return false;
|
||||||
|
@ -496,9 +496,15 @@ static qboolean addLeafToAccum( uint16_t leaf_index ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int addCompressedPVSLeafsToAccum(const model_t *const map, const byte *pvs, qboolean print_debug) {
|
static void leafAccumFinalize( void ) {
|
||||||
|
for (int i = 0; i < g_lights_bsp.accum.count; ++i)
|
||||||
|
g_lights_bsp.accum.leafs[i] &= 0xffffu;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int leafAccumAddPotentiallyVisibleFromLeaf(const model_t *const map, const mleaf_t *leaf, qboolean print_debug) {
|
||||||
int pvs_leaf_index = 0;
|
int pvs_leaf_index = 0;
|
||||||
int leafs_added = 0;
|
int leafs_added = 0;
|
||||||
|
const byte *pvs = leaf->compressed_vis;
|
||||||
for (;pvs_leaf_index < map->numleafs; ++pvs) {
|
for (;pvs_leaf_index < map->numleafs; ++pvs) {
|
||||||
uint8_t bits = pvs[0];
|
uint8_t bits = pvs[0];
|
||||||
|
|
||||||
|
@ -514,7 +520,7 @@ static int addCompressedPVSLeafsToAccum(const model_t *const map, const byte *pv
|
||||||
if ((bits&1) == 0)
|
if ((bits&1) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (addLeafToAccum( pvs_leaf_index + 1 )) {
|
if (leafAccumAdd( pvs_leaf_index + 1 )) {
|
||||||
leafs_added++;
|
leafs_added++;
|
||||||
if (print_debug)
|
if (print_debug)
|
||||||
gEngine.Con_Reportf(" .%d", pvs_leaf_index + 1);
|
gEngine.Con_Reportf(" .%d", pvs_leaf_index + 1);
|
||||||
|
@ -536,7 +542,7 @@ vk_light_leaf_set_t *getMapLeafsAffectedByMapSurface( const msurface_t *surf ) {
|
||||||
// Check if PVL hasn't been collected yet
|
// Check if PVL hasn't been collected yet
|
||||||
if (!smeta->potentially_visible_leafs) {
|
if (!smeta->potentially_visible_leafs) {
|
||||||
int leafs_direct = 0, leafs_pvs = 0;
|
int leafs_direct = 0, leafs_pvs = 0;
|
||||||
prepareLeafAccum();
|
leafAccumPrepare();
|
||||||
|
|
||||||
// Enumerate all the map leafs and pick ones that have this surface referenced
|
// Enumerate all the map leafs and pick ones that have this surface referenced
|
||||||
if (verbose_debug)
|
if (verbose_debug)
|
||||||
|
@ -550,7 +556,7 @@ vk_light_leaf_set_t *getMapLeafsAffectedByMapSurface( const msurface_t *surf ) {
|
||||||
|
|
||||||
// FIXME split direct leafs marking from pvs propagation
|
// FIXME split direct leafs marking from pvs propagation
|
||||||
leafs_direct++;
|
leafs_direct++;
|
||||||
if (addLeafToAccum( i )) {
|
if (leafAccumAdd( i )) {
|
||||||
if (verbose_debug)
|
if (verbose_debug)
|
||||||
gEngine.Con_Reportf(" %d", i);
|
gEngine.Con_Reportf(" %d", i);
|
||||||
} else {
|
} else {
|
||||||
|
@ -560,17 +566,19 @@ vk_light_leaf_set_t *getMapLeafsAffectedByMapSurface( const msurface_t *surf ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all PVS leafs
|
// Get all PVS leafs
|
||||||
leafs_pvs += addCompressedPVSLeafsToAccum(map, leaf->compressed_vis, verbose_debug);
|
leafs_pvs += leafAccumAddPotentiallyVisibleFromLeaf(map, leaf, verbose_debug);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (verbose_debug)
|
if (verbose_debug)
|
||||||
gEngine.Con_Reportf(" (sum=%d, direct=%d, pvs=%d)\n", g_lights_bsp.accum.count, leafs_direct, leafs_pvs);
|
gEngine.Con_Reportf(" (sum=%d, direct=%d, pvs=%d)\n", g_lights_bsp.accum.count, leafs_direct, leafs_pvs);
|
||||||
|
|
||||||
|
leafAccumFinalize();
|
||||||
|
|
||||||
smeta->potentially_visible_leafs = (vk_light_leaf_set_t*)Mem_Malloc(vk_core.pool, sizeof(smeta->potentially_visible_leafs) + sizeof(int) * g_lights_bsp.accum.count);
|
smeta->potentially_visible_leafs = (vk_light_leaf_set_t*)Mem_Malloc(vk_core.pool, sizeof(smeta->potentially_visible_leafs) + sizeof(int) * g_lights_bsp.accum.count);
|
||||||
smeta->potentially_visible_leafs->num = g_lights_bsp.accum.count;
|
smeta->potentially_visible_leafs->num = g_lights_bsp.accum.count;
|
||||||
|
|
||||||
for (int i = 0; i < g_lights_bsp.accum.count; ++i) {
|
for (int i = 0; i < g_lights_bsp.accum.count; ++i) {
|
||||||
smeta->potentially_visible_leafs->leafs[i] = g_lights_bsp.accum.leafs[i] & 0xffffu;
|
smeta->potentially_visible_leafs->leafs[i] = g_lights_bsp.accum.leafs[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,7 +630,6 @@ static int computeCellIndex( const int light_cell[3] ) {
|
||||||
return light_cell[0] + light_cell[1] * g_lights.map.grid_size[0] + light_cell[2] * g_lights.map.grid_size[0] * g_lights.map.grid_size[1];
|
return light_cell[0] + light_cell[1] * g_lights.map.grid_size[0] + light_cell[2] * g_lights.map.grid_size[0] * g_lights.map.grid_size[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
//static qboolean dump_fatpvs = true;
|
|
||||||
static qboolean have_surf = false;
|
static qboolean have_surf = false;
|
||||||
|
|
||||||
vk_light_leaf_set_t *getMapLeafsAffectedByMovingSurface( const msurface_t *surf, const matrix3x4 *transform_row ) {
|
vk_light_leaf_set_t *getMapLeafsAffectedByMovingSurface( const msurface_t *surf, const matrix3x4 *transform_row ) {
|
||||||
|
@ -655,7 +662,7 @@ vk_light_leaf_set_t *getMapLeafsAffectedByMovingSurface( const msurface_t *surf,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareLeafAccum();
|
leafAccumPrepare();
|
||||||
|
|
||||||
// TODO it's possible to somehow more efficiently traverse the bsp and collect only the affected leafs
|
// TODO it's possible to somehow more efficiently traverse the bsp and collect only the affected leafs
|
||||||
// (origin + radius will accidentally touch leafs that are really should not be affected)
|
// (origin + radius will accidentally touch leafs that are really should not be affected)
|
||||||
|
@ -671,7 +678,7 @@ vk_light_leaf_set_t *getMapLeafsAffectedByMovingSurface( const msurface_t *surf,
|
||||||
|
|
||||||
leafs_direct++;
|
leafs_direct++;
|
||||||
|
|
||||||
if (addLeafToAccum( i + 1 )) {
|
if (leafAccumAdd( i + 1 )) {
|
||||||
if (!have_surf || debug_dump_lights.enabled)
|
if (!have_surf || debug_dump_lights.enabled)
|
||||||
gEngine.Con_Reportf(" %d", i + 1);
|
gEngine.Con_Reportf(" %d", i + 1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -679,17 +686,12 @@ vk_light_leaf_set_t *getMapLeafsAffectedByMovingSurface( const msurface_t *surf,
|
||||||
// but it really should be counted as direct
|
// but it really should be counted as direct
|
||||||
leafs_pvs--;
|
leafs_pvs--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// it seems that FatPVS already implements PVS walk leafs_pvs += addCompressedPVSLeafsToAccum(map, leaf->compressed_vis, debug_dump_lights.enabled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!have_surf || debug_dump_lights.enabled)
|
if (!have_surf || debug_dump_lights.enabled)
|
||||||
gEngine.Con_Reportf(" (sum=%d, direct=%d, pvs=%d)\n", g_lights_bsp.accum.count, leafs_direct, leafs_pvs);
|
gEngine.Con_Reportf(" (sum=%d, direct=%d, pvs=%d)\n", g_lights_bsp.accum.count, leafs_direct, leafs_pvs);
|
||||||
|
|
||||||
//dump_fatpvs = false;
|
leafAccumFinalize();
|
||||||
|
|
||||||
for (int i = 0; i < g_lights_bsp.accum.count; ++i)
|
|
||||||
g_lights_bsp.accum.leafs[i] &= 0xffffu;
|
|
||||||
|
|
||||||
// ...... oh no
|
// ...... oh no
|
||||||
return (vk_light_leaf_set_t*)&g_lights_bsp.accum.count;
|
return (vk_light_leaf_set_t*)&g_lights_bsp.accum.count;
|
||||||
|
@ -745,10 +747,7 @@ static void prepareSurfacesLeafVisibilityCache( void ) {
|
||||||
g_lights_bsp.surfaces[i].potentially_visible_leafs = NULL;
|
g_lights_bsp.surfaces[i].potentially_visible_leafs = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void traverseBSP( void );
|
void VK_LightsNewMap( void ) {
|
||||||
|
|
||||||
void VK_LightsNewMap( void )
|
|
||||||
{
|
|
||||||
const model_t *map = gEngine.pfnGetModelByIndex( 1 );
|
const model_t *map = gEngine.pfnGetModelByIndex( 1 );
|
||||||
|
|
||||||
// 1. Determine map bounding box (and optimal grid size?)
|
// 1. Determine map bounding box (and optimal grid size?)
|
||||||
|
@ -786,14 +785,12 @@ void VK_LightsNewMap( void )
|
||||||
clusterBitMapShutdown();
|
clusterBitMapShutdown();
|
||||||
clusterBitMapInit();
|
clusterBitMapInit();
|
||||||
|
|
||||||
//traverseBSP();
|
|
||||||
prepareSurfacesLeafVisibilityCache();
|
prepareSurfacesLeafVisibilityCache();
|
||||||
|
|
||||||
VK_LightsLoadMapStaticLights();
|
VK_LightsLoadMapStaticLights();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VK_LightsLoadMapStaticLights( void )
|
void VK_LightsLoadMapStaticLights( void ) {
|
||||||
{
|
|
||||||
const model_t *map = gEngine.pfnGetModelByIndex( 1 );
|
const model_t *map = gEngine.pfnGetModelByIndex( 1 );
|
||||||
|
|
||||||
parseStaticLightEntities();
|
parseStaticLightEntities();
|
||||||
|
@ -832,6 +829,16 @@ static qboolean addSurfaceLightToCell( int cell_index, int emissive_surface_inde
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static qboolean addLightToCell( int cell_index, int light_index ) {
|
||||||
|
vk_lights_cell_t *const cluster = g_lights.cells + cell_index;
|
||||||
|
|
||||||
|
if (cluster->num_point_lights == MAX_VISIBLE_POINT_LIGHTS)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
cluster->point_lights[cluster->num_point_lights++] = light_index;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static qboolean canSurfaceLightAffectAABB(const model_t *mod, const msurface_t *surf, const vec3_t emissive, const float minmax[6]) {
|
static qboolean canSurfaceLightAffectAABB(const model_t *mod, const msurface_t *surf, const vec3_t emissive, const float minmax[6]) {
|
||||||
//APROF_SCOPE_BEGIN_EARLY(canSurfaceLightAffectAABB); // DO NOT DO THIS. We have like 600k of these calls per frame :feelsbadman:
|
//APROF_SCOPE_BEGIN_EARLY(canSurfaceLightAffectAABB); // DO NOT DO THIS. We have like 600k of these calls per frame :feelsbadman:
|
||||||
qboolean retval = true;
|
qboolean retval = true;
|
||||||
|
@ -975,12 +982,57 @@ fin:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void addPointLightToClusters( int index ) {
|
||||||
|
vk_point_light_t *const light = g_lights.point_lights + index;
|
||||||
|
const model_t* const world = gEngine.pfnGetModelByIndex( 1 );
|
||||||
|
const mleaf_t* leaf = gEngine.Mod_PointInLeaf(light->origin, world->nodes);
|
||||||
|
const vk_light_leaf_set_t *const leafs = (vk_light_leaf_set_t*)&g_lights_bsp.accum.count;
|
||||||
|
|
||||||
|
leafAccumPrepare();
|
||||||
|
leafAccumAddPotentiallyVisibleFromLeaf( world, leaf, false);
|
||||||
|
leafAccumFinalize();
|
||||||
|
|
||||||
|
clusterBitMapClear();
|
||||||
|
for (int i = 0; i < leafs->num; ++i) {
|
||||||
|
const mleaf_t *const leaf = world->leafs + leafs->leafs[i];
|
||||||
|
|
||||||
|
const int min_x = floorf(leaf->minmaxs[0] / LIGHT_GRID_CELL_SIZE);
|
||||||
|
const int min_y = floorf(leaf->minmaxs[1] / LIGHT_GRID_CELL_SIZE);
|
||||||
|
const int min_z = floorf(leaf->minmaxs[2] / LIGHT_GRID_CELL_SIZE);
|
||||||
|
|
||||||
|
const int max_x = ceilf(leaf->minmaxs[3] / LIGHT_GRID_CELL_SIZE);
|
||||||
|
const int max_y = ceilf(leaf->minmaxs[4] / LIGHT_GRID_CELL_SIZE);
|
||||||
|
const int max_z = ceilf(leaf->minmaxs[5] / LIGHT_GRID_CELL_SIZE);
|
||||||
|
|
||||||
|
for (int x = min_x; x < max_x; ++x)
|
||||||
|
for (int y = min_y; y < max_y; ++y)
|
||||||
|
for (int z = min_z; z < max_z; ++z) {
|
||||||
|
const int cell[3] = {
|
||||||
|
x - g_lights.map.grid_min_cell[0],
|
||||||
|
y - g_lights.map.grid_min_cell[1],
|
||||||
|
z - g_lights.map.grid_min_cell[2]
|
||||||
|
};
|
||||||
|
|
||||||
|
const int cell_index = computeCellIndex( cell );
|
||||||
|
if (cell_index < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (clusterBitMapCheckOrSet( cell_index )) {
|
||||||
|
if (!addLightToCell(cell_index, index)) {
|
||||||
|
// gEngine.Con_Printf(S_ERROR "Cluster %d,%d,%d(%d) ran out of light slots\n",
|
||||||
|
// cell[0], cell[1], cell[2], cell_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int addPointLight( const vec3_t origin, const vec3_t color, float radius, float hack_attenuation ) {
|
static int addPointLight( const vec3_t origin, const vec3_t color, float radius, float hack_attenuation ) {
|
||||||
const int index = g_lights.num_point_lights;
|
const int index = g_lights.num_point_lights;
|
||||||
vk_point_light_t *const plight = g_lights.point_lights + index;
|
vk_point_light_t *const plight = g_lights.point_lights + index;
|
||||||
|
|
||||||
if (g_lights.num_point_lights >= MAX_POINT_LIGHTS) {
|
if (g_lights.num_point_lights >= MAX_POINT_LIGHTS) {
|
||||||
gEngine.Con_Printf(S_ERROR "Too many dlights, MAX_POINT_LIGHTS=%d\n", MAX_POINT_LIGHTS);
|
gEngine.Con_Printf(S_ERROR "Too many lights, MAX_POINT_LIGHTS=%d\n", MAX_POINT_LIGHTS);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -999,6 +1051,7 @@ static int addPointLight( const vec3_t origin, const vec3_t color, float radius,
|
||||||
plight->stopdot = plight->stopdot2 = -1.f;
|
plight->stopdot = plight->stopdot2 = -1.f;
|
||||||
VectorSet(plight->dir, 0, 0, 0);
|
VectorSet(plight->dir, 0, 0, 0);
|
||||||
|
|
||||||
|
addPointLightToClusters( index );
|
||||||
g_lights.num_point_lights++;
|
g_lights.num_point_lights++;
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
@ -1008,7 +1061,7 @@ static int addSpotLight( const vk_light_entity_t *le, float radius, float hack_a
|
||||||
vk_point_light_t *const plight = g_lights.point_lights + index;
|
vk_point_light_t *const plight = g_lights.point_lights + index;
|
||||||
|
|
||||||
if (g_lights.num_point_lights >= MAX_POINT_LIGHTS) {
|
if (g_lights.num_point_lights >= MAX_POINT_LIGHTS) {
|
||||||
gEngine.Con_Printf(S_ERROR "Too many dlights, MAX_POINT_LIGHTS=%d\n", MAX_POINT_LIGHTS);
|
gEngine.Con_Printf(S_ERROR "Too many lights, MAX_POINT_LIGHTS=%d\n", MAX_POINT_LIGHTS);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1028,6 +1081,7 @@ static int addSpotLight( const vk_light_entity_t *le, float radius, float hack_a
|
||||||
plight->stopdot = le->stopdot;
|
plight->stopdot = le->stopdot;
|
||||||
plight->stopdot2 = le->stopdot2;
|
plight->stopdot2 = le->stopdot2;
|
||||||
|
|
||||||
|
addPointLightToClusters( index );
|
||||||
g_lights.num_point_lights++;
|
g_lights.num_point_lights++;
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue