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:
Ivan Avdeev 2022-01-14 23:48:57 -08:00
parent b31462fe18
commit 04a201c401
11 changed files with 230 additions and 155 deletions

View File

@ -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");
}

View File

@ -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];

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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)) {

View File

@ -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;

View File

@ -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++;
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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)

View File

@ -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)
{