rt: pass new polygon lights to shader naively
also start refactoring light collection broken: - reloading lights after patching - wagonchik lights (attached to non-static models) missing: - clustering the new poly lights - proper sampling, only rough estimate for now - shadows probably a lot more
This commit is contained in:
parent
b31462fe18
commit
04a201c401
|
@ -102,7 +102,7 @@ void XVK_CameraDebugPrintCenterEntity( void ) {
|
|||
|
||||
const vk_lights_cell_t *cell = (cell_index >= 0 && cell_index < MAX_LIGHT_CLUSTERS) ? g_lights.cells + cell_index : NULL;
|
||||
p += Q_snprintf(p, end - p,
|
||||
"light raw=(%d, %d, %d) cell=(%d, %d, %d) index=%d surf=%d point=%d\n",
|
||||
"light raw=(%d, %d, %d) cell=(%d, %d, %d) index=%d poly=%d point=%d\n",
|
||||
cell_raw[0],
|
||||
cell_raw[1],
|
||||
cell_raw[2],
|
||||
|
@ -110,13 +110,13 @@ void XVK_CameraDebugPrintCenterEntity( void ) {
|
|||
light_cell[1],
|
||||
light_cell[2],
|
||||
cell_index,
|
||||
cell ? cell->num_emissive_surfaces : -1,
|
||||
cell ? cell->num_polygons : -1,
|
||||
cell ? cell->num_point_lights : -1);
|
||||
|
||||
if (cell && cell->num_emissive_surfaces > 0) {
|
||||
p += Q_snprintf(p, end - p, "surf:");
|
||||
for (int i = 0; i < cell->num_emissive_surfaces; ++i) {
|
||||
p += Q_snprintf(p, end - p, " %d", cell->emissive_surfaces[i]);
|
||||
if (cell && cell->num_polygons > 0) {
|
||||
p += Q_snprintf(p, end - p, "poly:");
|
||||
for (int i = 0; i < cell->num_polygons; ++i) {
|
||||
p += Q_snprintf(p, end - p, " %d", cell->polygons[i]);
|
||||
}
|
||||
p += Q_snprintf(p, end - p, "\n");
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
layout (constant_id = 4) const float LIGHT_GRID_CELL_SIZE = 128.;// FIXME 256.;
|
||||
layout (constant_id = 5) const uint MAX_LIGHT_CLUSTERS = 262144;// FIXME 32768;
|
||||
layout (constant_id = 6) const uint MAX_TEXTURES = 4096;
|
||||
layout (set = 0, binding = BINDING_LIGHTS) uniform UBOLights { Lights lights; };
|
||||
layout (set = 0, binding = BINDING_LIGHTS) uniform UBOLights { Lights lights; }; // TODO this is pretty much static and should be a buffer, not UBO
|
||||
layout (set = 0, binding = BINDING_LIGHT_CLUSTERS, align = 1) readonly buffer UBOLightClusters {
|
||||
ivec3 grid_min, grid_size;
|
||||
//uint8_t clusters_data[MAX_LIGHT_CLUSTERS * LIGHT_CLUSTER_SIZE + HACK_OFFSET];
|
||||
|
|
|
@ -19,6 +19,7 @@ SampleContext buildSampleContext(vec3 position, vec3 normal, vec3 view_dir) {
|
|||
return ctx;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void sampleEmissiveSurface(vec3 P, vec3 N, vec3 throughput, vec3 view_dir, MaterialProperties material, SampleContext ctx, uint ekusok_index, out vec3 out_diffuse, out vec3 out_specular) {
|
||||
out_diffuse = out_specular = vec3(0.);
|
||||
|
||||
|
@ -185,3 +186,29 @@ void sampleEmissiveSurfaces(vec3 P, vec3 N, vec3 throughput, vec3 view_dir, Mate
|
|||
specular += lspecular * sampling_light_scale;
|
||||
} // for all emissive kusochki
|
||||
}
|
||||
#endif
|
||||
|
||||
// FIXME this is a quick test that reading new lights is possible
|
||||
void sampleEmissiveSurfaces(vec3 P, vec3 N, vec3 throughput, vec3 view_dir, MaterialProperties material, uint cluster_index, inout vec3 diffuse, inout vec3 specular) {
|
||||
|
||||
//diffuse = vec3(fract(float(lights.num_polygons) / 10.)); return;
|
||||
for (uint i = 0; i < lights.num_polygons; ++i) {
|
||||
const PolygonLight poly = lights.polygons[i];
|
||||
|
||||
/* diffuse += poly.emissive; */
|
||||
/* continue; */
|
||||
|
||||
const vec3 dir = poly.center - P;
|
||||
const vec3 light_dir = normalize(dir);
|
||||
const float contrib_estimate = dot(light_dir, poly.normal_area) / dot(dir, dir);
|
||||
|
||||
if (contrib_estimate < 1e-6)
|
||||
continue;
|
||||
|
||||
//const float area = 1.f / length(poly.normal_area);
|
||||
vec3 poly_diffuse = vec3(0.), poly_specular = vec3(0.);
|
||||
evalSplitBRDF(N, light_dir, view_dir, material, poly_diffuse, poly_specular);
|
||||
diffuse += throughput * poly.emissive * contrib_estimate;
|
||||
specular += throughput * poly.emissive * contrib_estimate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#define PAD(x)
|
||||
#define STRUCT
|
||||
|
||||
layout (constant_id = 0) const uint MAX_POINT_LIGHTS = 32;
|
||||
layout (constant_id = 0) const uint MAX_POINT_LIGHTS = 256;
|
||||
layout (constant_id = 1) const uint MAX_EMISSIVE_KUSOCHKI = 256;
|
||||
layout (constant_id = 2) const uint MAX_VISIBLE_POINT_LIGHTS = 63;
|
||||
layout (constant_id = 3) const uint MAX_VISIBLE_SURFACE_LIGHTS = 255;
|
||||
|
@ -82,12 +82,25 @@ struct EmissiveKusok {
|
|||
vec4 tx_row_x, tx_row_y, tx_row_z;
|
||||
};
|
||||
|
||||
struct PolygonLight {
|
||||
vec3 normal_area;
|
||||
uint vertices_begin;
|
||||
|
||||
vec3 center;
|
||||
uint vertices_count;
|
||||
|
||||
vec3 emissive;
|
||||
PAD(1)
|
||||
};
|
||||
|
||||
struct Lights {
|
||||
uint num_kusochki;
|
||||
uint num_polygons;
|
||||
uint num_point_lights;
|
||||
PAD(2)
|
||||
STRUCT EmissiveKusok kusochki[MAX_EMISSIVE_KUSOCHKI];
|
||||
//STRUCT EmissiveKusok kusochki[MAX_EMISSIVE_KUSOCHKI];
|
||||
STRUCT PointLight point_lights[MAX_POINT_LIGHTS];
|
||||
STRUCT PolygonLight polygons[MAX_EMISSIVE_KUSOCHKI];
|
||||
vec3 polygon_vertices[MAX_EMISSIVE_KUSOCHKI * 7];
|
||||
};
|
||||
|
||||
struct LightCluster {
|
||||
|
|
|
@ -439,59 +439,24 @@ static model_sizes_t computeSizes( const model_t *mod ) {
|
|||
}
|
||||
|
||||
static void loadEmissiveSurface(const model_t *mod, const int surface_index, const msurface_t *surf, const vec3_t emissive) {
|
||||
rt_light_polygon_t lpoly;
|
||||
rt_light_add_polygon_t lpoly;
|
||||
const qboolean flip = !!FBitSet( surf->flags, SURF_PLANEBACK );
|
||||
lpoly.num_vertices = Q_min(7, surf->numedges);
|
||||
|
||||
// TODO split, don't clip
|
||||
if (surf->numedges > 7)
|
||||
gEngine.Con_Printf(S_WARN "emissive surface %d has %d vertices; clipping to 7\n", surface_index, surf->numedges);
|
||||
|
||||
VectorCopy(emissive, lpoly.emissive);
|
||||
|
||||
VectorSet(lpoly.center, 0, 0, 0);
|
||||
VectorSet(lpoly.normal, 0, 0, 0);
|
||||
|
||||
for (int i = 0; i < lpoly.num_vertices; ++i) {
|
||||
const int iedge = mod->surfedges[surf->firstedge + i];
|
||||
const int index = flip ? lpoly.num_vertices - i - 1 : i;
|
||||
const int iedge = mod->surfedges[surf->firstedge + index];
|
||||
const medge_t *edge = mod->edges + (iedge >= 0 ? iedge : -iedge);
|
||||
const mvertex_t *vertex = mod->vertexes + (iedge >= 0 ? edge->v[0] : edge->v[1]);
|
||||
VectorCopy(vertex->position, lpoly.vertices[i]);
|
||||
VectorAdd(vertex->position, lpoly.center, lpoly.center);
|
||||
|
||||
if (i > 1) {
|
||||
vec3_t e[2], normal;
|
||||
VectorSubtract(lpoly.vertices[i-1], lpoly.vertices[i-2], e[0]);
|
||||
VectorSubtract(lpoly.vertices[i-0], lpoly.vertices[i-2], e[1]);
|
||||
CrossProduct(e[0], e[1], normal);
|
||||
VectorAdd(normal, lpoly.normal, lpoly.normal);
|
||||
}
|
||||
}
|
||||
|
||||
VectorM(1.f / lpoly.num_vertices, lpoly.center, lpoly.center);
|
||||
|
||||
lpoly.area = VectorLength(lpoly.normal);
|
||||
|
||||
VectorNormalize(lpoly.normal);
|
||||
{
|
||||
const float dot = DotProduct(lpoly.normal, surf->plane->normal);
|
||||
if (fabs(dot) < (1.f - 1e-5f)) {
|
||||
gEngine.Con_Reportf(S_WARN "surf=%d normal=(%f, %f, %f) computed=(%f, %f, %f) dot=%f dir=%d\n",
|
||||
surf->plane->normal[0],
|
||||
surf->plane->normal[1],
|
||||
surf->plane->normal[2],
|
||||
lpoly.normal[0],
|
||||
lpoly.normal[1],
|
||||
lpoly.normal[2],
|
||||
dot,
|
||||
!!FBitSet( surf->flags, SURF_PLANEBACK )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if( FBitSet( surf->flags, SURF_PLANEBACK ))
|
||||
VectorNegate( surf->plane->normal, lpoly.normal );
|
||||
else
|
||||
VectorCopy( surf->plane->normal, lpoly.normal );
|
||||
|
||||
RT_LightAddPolygon(&lpoly);
|
||||
}
|
||||
|
||||
|
@ -538,6 +503,7 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
|
|||
if (t != tex_id)
|
||||
continue;
|
||||
|
||||
// FIXME move this to rt_light_bsp and static loading
|
||||
{
|
||||
vec3_t emissive;
|
||||
if (psurf && (psurf->flags & Patch_Surface_Emissive)) {
|
||||
|
|
|
@ -46,5 +46,7 @@
|
|||
|
||||
#define ALIGN_UP(ptr, align) ((((ptr) + (align) - 1) / (align)) * (align))
|
||||
|
||||
#define COUNTOF(a) (sizeof(a)/sizeof((a)[0]))
|
||||
|
||||
extern ref_api_t gEngine;
|
||||
extern ref_globals_t *gpGlobals;
|
||||
|
|
|
@ -312,7 +312,7 @@ vk_light_leaf_set_t *getMapLeafsAffectedByMapSurface( const msurface_t *surf ) {
|
|||
|
||||
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[0]) + sizeof(int) * 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) {
|
||||
|
@ -450,9 +450,7 @@ static void prepareSurfacesLeafVisibilityCache( void ) {
|
|||
g_lights_bsp.surfaces[i].potentially_visible_leafs = NULL;
|
||||
}
|
||||
|
||||
void VK_LightsNewMap( void ) {
|
||||
const model_t *map = gEngine.pfnGetModelByIndex( 1 );
|
||||
|
||||
void RT_LightsNewMapBegin( const struct model_s *map ) {
|
||||
// 1. Determine map bounding box (and optimal grid size?)
|
||||
// map->mins, maxs
|
||||
vec3_t map_size, min_cell, max_cell;
|
||||
|
@ -503,31 +501,45 @@ void VK_LightsNewMap( void ) {
|
|||
|
||||
loadRadData( map, "%.*s.rad", name_len, map->name );
|
||||
}
|
||||
|
||||
// Clear static lights counts
|
||||
{
|
||||
g_lights.num_polygons = g_lights.num_static.polygons = 0;
|
||||
g_lights.num_point_lights = g_lights.num_static.point_lights = 0;
|
||||
g_lights.num_polygon_vertices = g_lights.num_static.polygon_vertices = 0;
|
||||
|
||||
for (int i = 0; i < g_lights.map.grid_cells; ++i) {
|
||||
vk_lights_cell_t *const cell = g_lights.cells + i;
|
||||
cell->num_point_lights = cell->num_static.point_lights = 0;
|
||||
cell->num_polygons = cell->num_static.polygons = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VK_LightsFrameInit( void ) {
|
||||
g_lights.num_emissive_surfaces = g_lights.num_static.emissive_surfaces;
|
||||
void RT_LightsFrameInit( void ) {
|
||||
g_lights.num_polygons = g_lights.num_static.polygons;
|
||||
g_lights.num_point_lights = g_lights.num_static.point_lights;
|
||||
g_lights.num_polygon_vertices = g_lights.num_static.polygon_vertices;
|
||||
|
||||
for (int i = 0; i < g_lights.map.grid_cells; ++i) {
|
||||
vk_lights_cell_t *const cell = g_lights.cells + i;
|
||||
cell->num_polygons = cell->num_static.polygons;
|
||||
cell->num_point_lights = cell->num_static.point_lights;
|
||||
cell->num_emissive_surfaces = cell->num_static.emissive_surfaces;
|
||||
}
|
||||
}
|
||||
|
||||
static qboolean addSurfaceLightToCell( int cell_index, int emissive_surface_index ) {
|
||||
vk_lights_cell_t *const cluster = g_lights.cells + cell_index;
|
||||
|
||||
if (cluster->num_emissive_surfaces == MAX_VISIBLE_SURFACE_LIGHTS) {
|
||||
if (cluster->num_polygons == MAX_VISIBLE_SURFACE_LIGHTS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debug_dump_lights.enabled) {
|
||||
gEngine.Con_Reportf(" adding surface light %d to cell %d (count=%d)\n", emissive_surface_index, cell_index, cluster->num_emissive_surfaces+1);
|
||||
gEngine.Con_Reportf(" adding surface light %d to cell %d (count=%d)\n", emissive_surface_index, cell_index, cluster->num_polygons+1);
|
||||
}
|
||||
|
||||
cluster->emissive_surfaces[cluster->num_emissive_surfaces++] = emissive_surface_index;
|
||||
cluster->polygons[cluster->num_polygons++] = emissive_surface_index;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -580,6 +592,7 @@ static qboolean canSurfaceLightAffectAABB(const model_t *mod, const msurface_t *
|
|||
return retval;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void VK_LightsAddEmissiveSurface( const struct vk_render_geometry_s *geom, const matrix3x4 *transform_row, qboolean static_map ) {
|
||||
APROF_SCOPE_BEGIN_EARLY(emissive_surface);
|
||||
const model_t* const world = gEngine.pfnGetModelByIndex( 1 );
|
||||
|
@ -620,13 +633,13 @@ void VK_LightsAddEmissiveSurface( const struct vk_render_geometry_s *geom, const
|
|||
}
|
||||
}
|
||||
|
||||
if (g_lights.num_emissive_surfaces >= 256)
|
||||
if (g_lights.num_polygons >= 256)
|
||||
goto fin;
|
||||
|
||||
if (debug_dump_lights.enabled) {
|
||||
const vk_texture_t *tex = findTexture(texture_num);
|
||||
ASSERT(tex);
|
||||
gEngine.Con_Reportf("surface light %d: %s (%f %f %f)\n", g_lights.num_emissive_surfaces, tex->name,
|
||||
gEngine.Con_Reportf("surface light %d: %s (%f %f %f)\n", g_lights.num_polygons, tex->name,
|
||||
emissive_color[0],
|
||||
emissive_color[1],
|
||||
emissive_color[2]);
|
||||
|
@ -636,7 +649,7 @@ void VK_LightsAddEmissiveSurface( const struct vk_render_geometry_s *geom, const
|
|||
const vk_light_leaf_set_t *const leafs = static_map
|
||||
? getMapLeafsAffectedByMapSurface( geom->surf )
|
||||
: getMapLeafsAffectedByMovingSurface( geom->surf, transform_row );
|
||||
vk_emissive_surface_t *esurf = g_lights.emissive_surfaces + g_lights.num_emissive_surfaces;
|
||||
vk_emissive_surface_t *esurf = g_lights.polygons + g_lights.num_polygons;
|
||||
|
||||
// Insert into emissive surfaces
|
||||
esurf->kusok_index = geom->kusok_index;
|
||||
|
@ -697,7 +710,7 @@ void VK_LightsAddEmissiveSurface( const struct vk_render_geometry_s *geom, const
|
|||
if (static_map && !canSurfaceLightAffectAABB(world, geom->surf, esurf->emissive, minmaxs))
|
||||
continue;
|
||||
|
||||
if (!addSurfaceLightToCell(cell_index, g_lights.num_emissive_surfaces)) {
|
||||
if (!addSurfaceLightToCell(cell_index, g_lights.num_polygons)) {
|
||||
ERROR_THROTTLED(10, "Cluster %d,%d,%d(%d) ran out of emissive surfaces slots",
|
||||
cell[0], cell[1], cell[2], cell_index);
|
||||
}
|
||||
|
@ -705,13 +718,14 @@ void VK_LightsAddEmissiveSurface( const struct vk_render_geometry_s *geom, const
|
|||
}
|
||||
}
|
||||
|
||||
++g_lights.num_emissive_surfaces;
|
||||
++g_lights.num_polygons;
|
||||
retval = esurf;
|
||||
}
|
||||
|
||||
fin:
|
||||
APROF_SCOPE_END(emissive_surface);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void addLightIndexToleaf( const mleaf_t *leaf, int index ) {
|
||||
const int min_x = floorf(leaf->minmaxs[0] / LIGHT_GRID_CELL_SIZE);
|
||||
|
@ -1014,25 +1028,12 @@ static void processStaticPointLights( void ) {
|
|||
APROF_SCOPE_END(static_lights);
|
||||
}
|
||||
|
||||
void VK_LightsLoadMapStaticLights( void ) {
|
||||
const model_t *map = gEngine.pfnGetModelByIndex( 1 );
|
||||
|
||||
void RT_LightsNewMapEnd( const struct model_s *map ) {
|
||||
//debug_dump_lights.enabled = true;
|
||||
|
||||
// Clear static lights counts
|
||||
{
|
||||
g_lights.num_emissive_surfaces = g_lights.num_static.emissive_surfaces = 0;
|
||||
g_lights.num_point_lights = g_lights.num_static.point_lights = 0;
|
||||
|
||||
for (int i = 0; i < g_lights.map.grid_cells; ++i) {
|
||||
vk_lights_cell_t *const cell = g_lights.cells + i;
|
||||
cell->num_point_lights = cell->num_static.point_lights = 0;
|
||||
cell->num_emissive_surfaces = cell->num_static.emissive_surfaces = 0;
|
||||
}
|
||||
}
|
||||
|
||||
processStaticPointLights();
|
||||
|
||||
#if 0
|
||||
// Load static map model
|
||||
{
|
||||
matrix3x4 xform;
|
||||
|
@ -1046,16 +1047,18 @@ void VK_LightsLoadMapStaticLights( void ) {
|
|||
// TODO how to differentiate between this and non-emissive gEngine.Con_Printf(S_ERROR "Ran out of surface light slots, geom %d of %d\n", i, bmodel->render_model.num_geometries);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Fix static counts
|
||||
{
|
||||
g_lights.num_static.emissive_surfaces = g_lights.num_emissive_surfaces;
|
||||
g_lights.num_static.polygons = g_lights.num_polygons;
|
||||
g_lights.num_static.point_lights = g_lights.num_point_lights;
|
||||
g_lights.num_static.polygon_vertices = g_lights.num_polygon_vertices;
|
||||
|
||||
for (int i = 0; i < g_lights.map.grid_cells; ++i) {
|
||||
vk_lights_cell_t *const cell = g_lights.cells + i;
|
||||
cell->num_static.point_lights = cell->num_point_lights;
|
||||
cell->num_static.emissive_surfaces = cell->num_emissive_surfaces;
|
||||
cell->num_static.polygons = cell->num_polygons;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1079,9 +1082,9 @@ void VK_LightsFrameFinalize( void ) {
|
|||
APROF_SCOPE_BEGIN_EARLY(finalize);
|
||||
const model_t* const world = gEngine.pfnGetModelByIndex( 1 );
|
||||
|
||||
if (g_lights.num_emissive_surfaces > UINT8_MAX) {
|
||||
ERROR_THROTTLED(10, "Too many emissive surfaces found: %d; some areas will be dark", g_lights.num_emissive_surfaces);
|
||||
g_lights.num_emissive_surfaces = UINT8_MAX;
|
||||
if (g_lights.num_polygons > UINT8_MAX) {
|
||||
ERROR_THROTTLED(10, "Too many emissive surfaces found: %d; some areas will be dark", g_lights.num_polygons);
|
||||
g_lights.num_polygons = UINT8_MAX;
|
||||
}
|
||||
|
||||
/* for (int i = 0; i < MAX_ELIGHTS; ++i) { */
|
||||
|
@ -1115,14 +1118,14 @@ void VK_LightsFrameFinalize( void ) {
|
|||
if (debug_dump_lights.enabled) {
|
||||
#if 0
|
||||
// Print light grid stats
|
||||
gEngine.Con_Reportf("Emissive surfaces found: %d\n", g_lights.num_emissive_surfaces);
|
||||
gEngine.Con_Reportf("Emissive surfaces found: %d\n", g_lights.num_polygons);
|
||||
|
||||
{
|
||||
#define GROUPSIZE 4
|
||||
int histogram[1 + (MAX_VISIBLE_SURFACE_LIGHTS + GROUPSIZE - 1) / GROUPSIZE] = {0};
|
||||
for (int i = 0; i < g_lights.map.grid_cells; ++i) {
|
||||
const vk_lights_cell_t *cluster = g_lights.cells + i;
|
||||
const int hist_index = cluster->num_emissive_surfaces ? 1 + cluster->num_emissive_surfaces / GROUPSIZE : 0;
|
||||
const int hist_index = cluster->num_polygons ? 1 + cluster->num_polygons / GROUPSIZE : 0;
|
||||
histogram[hist_index]++;
|
||||
}
|
||||
|
||||
|
@ -1139,12 +1142,12 @@ void VK_LightsFrameFinalize( void ) {
|
|||
int num_clusters_with_lights_in_range = 0;
|
||||
for (int i = 0; i < g_lights.map.grid_cells; ++i) {
|
||||
const vk_lights_cell_t *cluster = g_lights.cells + i;
|
||||
if (cluster->num_emissive_surfaces > 0) {
|
||||
gEngine.Con_Reportf(" cluster %d: emissive_surfaces=%d\n", i, cluster->num_emissive_surfaces);
|
||||
if (cluster->num_polygons > 0) {
|
||||
gEngine.Con_Reportf(" cluster %d: polygons=%d\n", i, cluster->num_polygons);
|
||||
}
|
||||
|
||||
for (int j = 0; j < cluster->num_emissive_surfaces; ++j) {
|
||||
const int index = cluster->emissive_surfaces[j];
|
||||
for (int j = 0; j < cluster->num_polygons; ++j) {
|
||||
const int index = cluster->polygons[j];
|
||||
if (index >= vk_rtx_light_begin->value && index < vk_rtx_light_end->value) {
|
||||
++num_clusters_with_lights_in_range;
|
||||
}
|
||||
|
@ -1160,17 +1163,57 @@ void VK_LightsFrameFinalize( void ) {
|
|||
APROF_SCOPE_END(finalize);
|
||||
}
|
||||
|
||||
int RT_LightAddPolygon(const rt_light_polygon_t *lpoly) {
|
||||
gEngine.Con_Reportf("RT_LightAddPolygon center=(%f, %f, %f) normal=(%f, %f, %f) area=%f num_vertices=%d\n",
|
||||
lpoly->center[0],
|
||||
lpoly->center[1],
|
||||
lpoly->center[2],
|
||||
lpoly->normal[0],
|
||||
lpoly->normal[1],
|
||||
lpoly->normal[2],
|
||||
lpoly->area,
|
||||
lpoly->num_vertices
|
||||
);
|
||||
int RT_LightAddPolygon(const rt_light_add_polygon_t *addpoly) {
|
||||
if (g_lights.num_polygons == MAX_SURFACE_LIGHTS) {
|
||||
gEngine.Con_Printf(S_ERROR "Max number of polygon lights %d reached\n", MAX_SURFACE_LIGHTS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
ASSERT(addpoly->num_vertices > 2);
|
||||
ASSERT(addpoly->num_vertices < 8);
|
||||
ASSERT(g_lights.num_polygon_vertices + addpoly->num_vertices <= COUNTOF(g_lights.polygon_vertices));
|
||||
|
||||
{
|
||||
rt_light_polygon_t *const poly = g_lights.polygons + g_lights.num_polygons;
|
||||
|
||||
poly->vertices.begin = g_lights.num_polygon_vertices;
|
||||
poly->vertices.count = addpoly->num_vertices;
|
||||
|
||||
VectorCopy(addpoly->emissive, poly->emissive);
|
||||
VectorSet(poly->center, 0, 0, 0);
|
||||
VectorSet(poly->normal_area, 0, 0, 0);
|
||||
|
||||
for (int i = 0; i < addpoly->num_vertices; ++i) {
|
||||
VectorCopy(addpoly->vertices[i], g_lights.polygon_vertices[poly->vertices.begin + i]);
|
||||
VectorAdd(addpoly->vertices[i], poly->center, poly->center);
|
||||
|
||||
if (i > 1) {
|
||||
vec3_t e[2], normal;
|
||||
VectorSubtract(addpoly->vertices[i-1], addpoly->vertices[i-2], e[0]);
|
||||
VectorSubtract(addpoly->vertices[i-0], addpoly->vertices[i-2], e[1]);
|
||||
CrossProduct(e[0], e[1], normal);
|
||||
VectorAdd(normal, poly->normal_area, poly->normal_area);
|
||||
}
|
||||
}
|
||||
|
||||
VectorM(1.f / poly->vertices.count, poly->center, poly->center);
|
||||
|
||||
gEngine.Con_Reportf("added polygon light index=%d color=(%f, %f, %f) center=(%f, %f, %f) normal_area=(%f, %f, %f) area=%f num_vertices=%d\n",
|
||||
g_lights.num_polygons,
|
||||
poly->emissive[0],
|
||||
poly->emissive[1],
|
||||
poly->emissive[2],
|
||||
poly->center[0],
|
||||
poly->center[1],
|
||||
poly->center[2],
|
||||
poly->normal_area[0],
|
||||
poly->normal_area[1],
|
||||
poly->normal_area[2],
|
||||
VectorLength(poly->normal_area),
|
||||
poly->vertices.count
|
||||
);
|
||||
|
||||
g_lights.num_polygon_vertices += addpoly->num_vertices;
|
||||
return g_lights.num_polygons++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
#include "vk_const.h"
|
||||
|
||||
#include "xash3d_types.h"
|
||||
#include "protocol.h"
|
||||
#include "const.h"
|
||||
#include "bspfile.h"
|
||||
//#include "protocol.h"
|
||||
//#include "const.h"
|
||||
//#include "bspfile.h"
|
||||
|
||||
typedef struct {
|
||||
vec3_t emissive;
|
||||
|
@ -14,29 +14,28 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
uint8_t num_point_lights;
|
||||
uint8_t num_emissive_surfaces;
|
||||
uint8_t num_polygons;
|
||||
|
||||
uint8_t point_lights[MAX_VISIBLE_POINT_LIGHTS];
|
||||
uint8_t emissive_surfaces[MAX_VISIBLE_SURFACE_LIGHTS];
|
||||
uint8_t polygons[MAX_VISIBLE_SURFACE_LIGHTS];
|
||||
|
||||
struct {
|
||||
uint8_t point_lights;
|
||||
uint8_t emissive_surfaces;
|
||||
uint8_t polygons;
|
||||
} num_static;
|
||||
} vk_lights_cell_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t emissive;
|
||||
uint32_t kusok_index;
|
||||
matrix3x4 transform;
|
||||
} vk_emissive_surface_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t emissive;
|
||||
vec3_t normal;
|
||||
vec3_t normal_area;
|
||||
vec3_t center;
|
||||
float area;
|
||||
int num_vertices;
|
||||
vec3_t vertices[7];
|
||||
//float area;
|
||||
|
||||
struct {
|
||||
int begin, count; // reference g_light.polygon_vertices
|
||||
} vertices;
|
||||
|
||||
// uint32_t kusok_index;
|
||||
} rt_light_polygon_t;
|
||||
|
||||
|
@ -67,20 +66,19 @@ typedef struct {
|
|||
vk_emissive_texture_t emissive_textures[MAX_TEXTURES];
|
||||
} map;
|
||||
|
||||
// FIXME deprecate
|
||||
int num_emissive_surfaces;
|
||||
vk_emissive_surface_t emissive_surfaces[MAX_SURFACE_LIGHTS];
|
||||
|
||||
int num_light_polygons;
|
||||
rt_light_polygon_t light_polygons[MAX_SURFACE_LIGHTS];
|
||||
|
||||
int num_polygons;
|
||||
rt_light_polygon_t polygons[MAX_SURFACE_LIGHTS];
|
||||
|
||||
int num_point_lights;
|
||||
vk_point_light_t point_lights[MAX_POINT_LIGHTS];
|
||||
|
||||
int num_polygon_vertices;
|
||||
vec3_t polygon_vertices[MAX_SURFACE_LIGHTS * 7];
|
||||
|
||||
struct {
|
||||
int emissive_surfaces;
|
||||
int point_lights;
|
||||
int polygons;
|
||||
int polygon_vertices;
|
||||
} num_static;
|
||||
|
||||
vk_lights_cell_t cells[MAX_LIGHT_CLUSTERS];
|
||||
|
@ -91,10 +89,11 @@ extern vk_lights_t g_lights;
|
|||
void VK_LightsInit( void );
|
||||
void VK_LightsShutdown( void );
|
||||
|
||||
void VK_LightsNewMap( void );
|
||||
void VK_LightsLoadMapStaticLights( void );
|
||||
struct model_s;
|
||||
void RT_LightsNewMapBegin( const struct model_s *map );
|
||||
void RT_LightsNewMapEnd( const struct model_s *map );
|
||||
|
||||
void VK_LightsFrameInit( void );
|
||||
void RT_LightsFrameInit( void ); // TODO begin
|
||||
|
||||
// TODO there is an arguably better way to organize this.
|
||||
// a. this only belongs to ray tracing mode
|
||||
|
@ -104,11 +103,24 @@ struct vk_render_geometry_s;
|
|||
void VK_LightsAddEmissiveSurface( const struct vk_render_geometry_s *geom, const matrix3x4 *transform_row, qboolean static_map );
|
||||
qboolean RT_GetEmissiveForTexture( vec3_t out, int texture_id );
|
||||
|
||||
int RT_LightAddPolygon(const rt_light_polygon_t *light);
|
||||
|
||||
void VK_LightsFrameFinalize( void );
|
||||
void VK_LightsFrameFinalize( void ); // TODO end
|
||||
|
||||
int R_LightCellIndex( const int light_cell[3] );
|
||||
|
||||
struct cl_entity_s;
|
||||
void R_LightAddFlashlight( const struct cl_entity_s *ent, qboolean local_player );
|
||||
|
||||
struct msurface_s;
|
||||
typedef struct {
|
||||
int num_vertices;
|
||||
vec3_t vertices[7];
|
||||
|
||||
vec3_t emissive;
|
||||
|
||||
// Needed for BSP visibilty purposes
|
||||
// TODO can we layer light code? like:
|
||||
// - bsp/xash/rad/patch-specific stuff
|
||||
// - mostly engine-agnostic light clusters
|
||||
const struct msurface_s *surface;
|
||||
} rt_light_add_polygon_t;
|
||||
int RT_LightAddPolygon(const rt_light_add_polygon_t *light);
|
||||
|
|
|
@ -369,8 +369,8 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render
|
|||
const xvk_material_t *const mat = XVK_GetMaterialForTextureIndex( geom->texture );
|
||||
ASSERT(mat);
|
||||
|
||||
if (!render_model->static_map)
|
||||
VK_LightsAddEmissiveSurface( geom, transform_row, false );
|
||||
/* if (!render_model->static_map) */
|
||||
/* VK_LightsAddEmissiveSurface( geom, transform_row, false ); */
|
||||
|
||||
kusok->tex_base_color = mat->tex_base_color;
|
||||
kusok->tex_roughness = mat->tex_roughness;
|
||||
|
|
|
@ -354,15 +354,16 @@ void VK_RayFrameBegin( void )
|
|||
// TODO: move all lighting update to scene?
|
||||
if (g_rtx.reload_lighting) {
|
||||
g_rtx.reload_lighting = false;
|
||||
VK_LightsLoadMapStaticLights();
|
||||
// FIXME temporarily not supported VK_LightsLoadMapStaticLights();
|
||||
}
|
||||
|
||||
// TODO shouldn't we do this in freeze models mode anyway?
|
||||
VK_LightsFrameInit();
|
||||
RT_LightsFrameInit();
|
||||
}
|
||||
|
||||
static void createPipeline( void )
|
||||
{
|
||||
return; // ... FIXME
|
||||
struct RayShaderSpec {
|
||||
int max_point_lights;
|
||||
int max_emissive_kusochki;
|
||||
|
@ -757,7 +758,7 @@ static qboolean rayTrace( VkCommandBuffer cmdbuf, const xvk_ray_frame_images_t *
|
|||
}
|
||||
|
||||
// Finalize and update dynamic lights
|
||||
static void uploadLights ( void ) {
|
||||
static void uploadLights( void ) {
|
||||
// Upload light grid
|
||||
{
|
||||
vk_ray_shader_light_grid *grid = g_rtx.light_grid_buffer.mapped;
|
||||
|
@ -770,24 +771,28 @@ static void uploadLights ( void ) {
|
|||
struct LightCluster *const dst = grid->cells + i;
|
||||
|
||||
dst->num_point_lights = src->num_point_lights;
|
||||
dst->num_emissive_surfaces = src->num_emissive_surfaces;
|
||||
dst->num_emissive_surfaces = src->num_polygons;
|
||||
memcpy(dst->point_lights, src->point_lights, sizeof(uint8_t) * src->num_point_lights);
|
||||
memcpy(dst->emissive_surfaces, src->emissive_surfaces, sizeof(uint8_t) * src->num_emissive_surfaces);
|
||||
memcpy(dst->emissive_surfaces, src->polygons, sizeof(uint8_t) * src->num_polygons);
|
||||
}
|
||||
}
|
||||
|
||||
// Upload dynamic emissive kusochki
|
||||
{
|
||||
struct Lights *lights = g_ray_model_state.lights_buffer.mapped;
|
||||
ASSERT(g_lights.num_emissive_surfaces <= MAX_EMISSIVE_KUSOCHKI);
|
||||
lights->num_kusochki = g_lights.num_emissive_surfaces;
|
||||
for (int i = 0; i < g_lights.num_emissive_surfaces; ++i) {
|
||||
const vk_emissive_surface_t *const src_esurf = g_lights.emissive_surfaces + i;
|
||||
struct EmissiveKusok *const dst_ekusok = lights->kusochki + i;
|
||||
ASSERT(g_lights.num_polygons <= MAX_EMISSIVE_KUSOCHKI);
|
||||
lights->num_polygons = g_lights.num_polygons;
|
||||
for (int i = 0; i < g_lights.num_polygons; ++i) {
|
||||
const rt_light_polygon_t *const src_poly = g_lights.polygons + i;
|
||||
struct PolygonLight *const dst_poly = lights->polygons + i;
|
||||
|
||||
dst_ekusok->kusok_index = src_esurf->kusok_index;
|
||||
Matrix3x4_Copy(dst_ekusok->tx_row_x, src_esurf->transform);
|
||||
VectorCopy(src_esurf->emissive, dst_ekusok->emissive);
|
||||
//dst_ekusok->kusok_index = src_esurf->kusok_index;
|
||||
//Matrix3x4_Copy(dst_ekusok->tx_row_x, src_esurf->transform);
|
||||
VectorCopy(src_poly->emissive, dst_poly->emissive);
|
||||
VectorCopy(src_poly->normal_area, dst_poly->normal_area);
|
||||
VectorCopy(src_poly->center, dst_poly->center);
|
||||
dst_poly->vertices_begin = src_poly->vertices.begin;
|
||||
dst_poly->vertices_count = src_poly->vertices.count;
|
||||
}
|
||||
|
||||
lights->num_point_lights = g_lights.num_point_lights;
|
||||
|
@ -806,6 +811,10 @@ static void uploadLights ( void ) {
|
|||
|
||||
dst->environment = !!(src->flags & LightFlag_Environment);
|
||||
}
|
||||
|
||||
// TODO static assert
|
||||
ASSERT(sizeof(lights->polygon_vertices) == sizeof(g_lights.polygon_vertices));
|
||||
memcpy(lights->polygon_vertices, g_lights.polygon_vertices, sizeof(lights->polygon_vertices));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1182,7 +1191,7 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args)
|
|||
deinitVk2d();
|
||||
initVk2d();
|
||||
// TODO gracefully handle reload errors: need to change createPipeline, loadShader, VK_PipelineCreate...
|
||||
vkDestroyPipeline(vk_core.device, g_rtx.pipeline, NULL);
|
||||
//vkDestroyPipeline(vk_core.device, g_rtx.pipeline, NULL);
|
||||
createPipeline();
|
||||
|
||||
XVK_RayTracePrimaryReloadPipeline();
|
||||
|
@ -1490,7 +1499,7 @@ RAY_LIGHT_DIRECT_OUTPUTS(X)
|
|||
XVK_ImageDestroy(&g_rtx.frames[i].additive);
|
||||
}
|
||||
|
||||
vkDestroyPipeline(vk_core.device, g_rtx.pipeline, NULL);
|
||||
//vkDestroyPipeline(vk_core.device, g_rtx.pipeline, NULL);
|
||||
VK_DescriptorsDestroy(&g_rtx.descriptors);
|
||||
|
||||
if (g_rtx.tlas != VK_NULL_HANDLE)
|
||||
|
|
|
@ -54,7 +54,9 @@ static void reloadPatches( void ) {
|
|||
// Assumes that the map brush model has been loaded
|
||||
|
||||
// Patching does disturb light sources, reinitialize
|
||||
VK_LightsLoadMapStaticLights();
|
||||
|
||||
// FIXME loading patches will be broken now ;_;
|
||||
// ?? VK_LightsLoadMapStaticLights();
|
||||
}
|
||||
|
||||
static void reloadMaterials( void ) {
|
||||
|
@ -67,7 +69,8 @@ static void reloadMaterials( void ) {
|
|||
// Assumes that the map has been loaded
|
||||
|
||||
// Might have loaded new patch data, need to reload lighting data just in case
|
||||
VK_LightsLoadMapStaticLights();
|
||||
// FIXME loading patches will be broken now ;_;
|
||||
// ??? VK_LightsLoadMapStaticLights();
|
||||
}
|
||||
|
||||
void VK_SceneInit( void )
|
||||
|
@ -118,9 +121,9 @@ int R_FIXME_GetEntityRenderMode( cl_entity_t *ent )
|
|||
}
|
||||
|
||||
// tell the renderer what new map is started
|
||||
void R_NewMap( void )
|
||||
{
|
||||
void R_NewMap( void ) {
|
||||
const int num_models = gEngine.EngineGetParm( PARM_NUMMODELS, 0 );
|
||||
const model_t *const map = gEngine.pfnGetModelByIndex( 1 );
|
||||
|
||||
// Existence of cache.data for the world means that we've already have loaded this map
|
||||
// and this R_NewMap call is from within loading of a saved game.
|
||||
|
@ -169,7 +172,7 @@ void R_NewMap( void )
|
|||
XVK_ParseMapPatches();
|
||||
|
||||
// Need parsed map entities, and also should happen before brush model loading
|
||||
VK_LightsNewMap();
|
||||
RT_LightsNewMapBegin(map);
|
||||
|
||||
// Load all models at once
|
||||
gEngine.Con_Reportf( "Num models: %d:\n", num_models );
|
||||
|
@ -192,7 +195,7 @@ void R_NewMap( void )
|
|||
|
||||
// Load static map lights
|
||||
// Reads surfaces from loaded brush models (must happen after all brushes are loaded)
|
||||
VK_LightsLoadMapStaticLights();
|
||||
RT_LightsNewMapEnd(map);
|
||||
|
||||
if (vk_core.rtx)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue