rt: refactor loading surface lights, fix #417
Do not entangle brush model loading with loading surface lights. Do a separate pass over brush model surfaces for the sole purpose of finding light sources. Enables consistent live-reloading light data after patching entities/surface/rad files.
This commit is contained in:
parent
58c9a9920e
commit
a284567002
|
@ -459,8 +459,6 @@ typedef struct {
|
|||
int num_surfaces, num_vertices, num_indices;
|
||||
int max_texture_id;
|
||||
int water_surfaces;
|
||||
//int sky_surfaces;
|
||||
int emissive_surfaces;
|
||||
} model_sizes_t;
|
||||
|
||||
static model_sizes_t computeSizes( const model_t *mod ) {
|
||||
|
@ -482,39 +480,11 @@ static model_sizes_t computeSizes( const model_t *mod ) {
|
|||
sizes.num_indices += 3 * (surf->numedges - 1);
|
||||
if (tex_id > sizes.max_texture_id)
|
||||
sizes.max_texture_id = tex_id;
|
||||
|
||||
{
|
||||
const xvk_patch_surface_t *const psurf = R_VkPatchGetSurface(i);
|
||||
vec3_t emissive;
|
||||
if ((psurf && (psurf->flags & Patch_Surface_Emissive)) || (RT_GetEmissiveForTexture(emissive, tex_id)))
|
||||
++sizes.emissive_surfaces;
|
||||
}
|
||||
}
|
||||
|
||||
return sizes;
|
||||
}
|
||||
|
||||
static rt_light_add_polygon_t loadPolyLight(const model_t *mod, const int surface_index, const msurface_t *surf, const vec3_t emissive) {
|
||||
rt_light_add_polygon_t lpoly = {0};
|
||||
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);
|
||||
|
||||
for (int i = 0; i < lpoly.num_vertices; ++i) {
|
||||
const int iedge = mod->surfedges[surf->firstedge + i];
|
||||
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]);
|
||||
}
|
||||
|
||||
lpoly.surface = surf;
|
||||
return lpoly;
|
||||
}
|
||||
|
||||
static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
|
||||
vk_brush_model_t *bmodel = mod->cache.data;
|
||||
uint32_t vertex_offset = 0;
|
||||
|
@ -556,30 +526,6 @@ 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
|
||||
{
|
||||
qboolean is_emissive = false;
|
||||
vec3_t emissive = {0};
|
||||
rt_light_add_polygon_t polylight;
|
||||
|
||||
if (psurf && (psurf->flags & Patch_Surface_Emissive)) {
|
||||
is_emissive = true;
|
||||
VectorCopy(psurf->emissive, emissive);
|
||||
} else if (RT_GetEmissiveForTexture(emissive, tex_id)) {
|
||||
is_emissive = true;
|
||||
}
|
||||
|
||||
if (is_emissive) {
|
||||
if (bmodel->render_model.polylights) {
|
||||
ASSERT(bmodel->render_model.polylights_count < sizes.emissive_surfaces);
|
||||
bmodel->render_model.polylights[bmodel->render_model.polylights_count++] = loadPolyLight(mod, surface_index, surf, emissive);
|
||||
} else {
|
||||
polylight = loadPolyLight(mod, surface_index, surf, emissive);
|
||||
RT_LightAddPolygon(&polylight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++num_geometries;
|
||||
|
||||
//gEngine.Con_Reportf( "surface %d: numverts=%d numedges=%d\n", i, surf->polys ? surf->polys->numverts : -1, surf->numedges );
|
||||
|
@ -680,10 +626,8 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
|
|||
|
||||
R_GeometryBufferUnlock( &buffer );
|
||||
|
||||
if (bmodel->render_model.polylights) {
|
||||
gEngine.Con_Reportf("Dynamic polylights %d %d \n", sizes.emissive_surfaces, bmodel->render_model.polylights_count);
|
||||
ASSERT(sizes.emissive_surfaces == bmodel->render_model.polylights_count);
|
||||
}
|
||||
bmodel->render_model.dynamic_polylights = NULL;
|
||||
bmodel->render_model.dynamic_polylights_count = 0;
|
||||
|
||||
ASSERT(sizes.num_surfaces == num_geometries);
|
||||
bmodel->render_model.num_geometries = num_geometries;
|
||||
|
@ -691,10 +635,8 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
|
|||
return true;
|
||||
}
|
||||
|
||||
qboolean VK_BrushModelLoad( model_t *mod, qboolean map )
|
||||
{
|
||||
if (mod->cache.data)
|
||||
{
|
||||
qboolean VK_BrushModelLoad( model_t *mod ) {
|
||||
if (mod->cache.data) {
|
||||
gEngine.Con_Reportf( S_WARN "Model %s was already loaded\n", mod->name );
|
||||
return true;
|
||||
}
|
||||
|
@ -711,7 +653,6 @@ qboolean VK_BrushModelLoad( model_t *mod, qboolean map )
|
|||
mod->cache.data = bmodel;
|
||||
Q_strncpy(bmodel->render_model.debug_name, mod->name, sizeof(bmodel->render_model.debug_name));
|
||||
bmodel->render_model.render_type = kVkRenderTypeSolid;
|
||||
bmodel->render_model.static_map = map;
|
||||
|
||||
bmodel->num_water_surfaces = sizes.water_surfaces;
|
||||
Vector4Set(bmodel->render_model.color, 1, 1, 1, 1);
|
||||
|
@ -719,9 +660,6 @@ qboolean VK_BrushModelLoad( model_t *mod, qboolean map )
|
|||
if (sizes.num_surfaces != 0) {
|
||||
bmodel->render_model.geometries = (vk_render_geometry_t*)((char*)(bmodel + 1));
|
||||
|
||||
if (!map && sizes.emissive_surfaces)
|
||||
bmodel->render_model.polylights = Mem_Malloc(vk_core.pool, sizeof(bmodel->render_model.polylights[0]) * sizes.emissive_surfaces);
|
||||
|
||||
if (!loadBrushSurfaces(sizes, mod) || !VK_RenderModelInit(&bmodel->render_model)) {
|
||||
gEngine.Con_Printf(S_ERROR "Could not load model %s\n", mod->name);
|
||||
Mem_Free(bmodel);
|
||||
|
@ -745,8 +683,6 @@ void VK_BrushModelDestroy( model_t *mod ) {
|
|||
return;
|
||||
|
||||
VK_RenderModelDestroy(&bmodel->render_model);
|
||||
if (bmodel->render_model.polylights)
|
||||
Mem_Free(bmodel->render_model.polylights);
|
||||
Mem_Free(bmodel);
|
||||
mod->cache.data = NULL;
|
||||
}
|
||||
|
@ -757,3 +693,83 @@ void VK_BrushStatsClear( void )
|
|||
g_brush.stat.num_vertices = 0;
|
||||
g_brush.stat.num_indices = 0;
|
||||
}
|
||||
|
||||
static rt_light_add_polygon_t loadPolyLight(const model_t *mod, const int surface_index, const msurface_t *surf, const vec3_t emissive) {
|
||||
rt_light_add_polygon_t lpoly = {0};
|
||||
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);
|
||||
|
||||
for (int i = 0; i < lpoly.num_vertices; ++i) {
|
||||
const int iedge = mod->surfedges[surf->firstedge + i];
|
||||
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]);
|
||||
}
|
||||
|
||||
lpoly.surface = surf;
|
||||
return lpoly;
|
||||
}
|
||||
|
||||
void R_VkBrushModelCollectEmissiveSurfaces( const struct model_s *mod, qboolean is_worldmodel ) {
|
||||
typedef struct {
|
||||
int model_surface_index;
|
||||
int surface_index;
|
||||
const msurface_t *surf;
|
||||
vec3_t emissive;
|
||||
} emissive_surface_t;
|
||||
emissive_surface_t emissive_surfaces[MAX_SURFACE_LIGHTS];
|
||||
int emissive_surfaces_count = 0;
|
||||
|
||||
for( int i = 0; i < mod->nummodelsurfaces; ++i) {
|
||||
const int surface_index = mod->firstmodelsurface + i;
|
||||
const msurface_t *surf = mod->surfaces + surface_index;
|
||||
|
||||
if (!renderableSurface(surf, surface_index))
|
||||
continue;
|
||||
|
||||
const int tex_id = surf->texinfo->texture->gl_texturenum; // TODO animation?
|
||||
const xvk_patch_surface_t *const psurf = R_VkPatchGetSurface(surface_index);
|
||||
|
||||
vec3_t emissive;
|
||||
if ((psurf && (psurf->flags & Patch_Surface_Emissive)) || (RT_GetEmissiveForTexture(emissive, tex_id))) {
|
||||
if (emissive_surfaces_count == MAX_SURFACE_LIGHTS) {
|
||||
gEngine.Con_Printf(S_ERROR "Too many emissive surfaces for model %s: max=%d\n", mod->name, MAX_SURFACE_LIGHTS);
|
||||
break;
|
||||
}
|
||||
|
||||
emissive_surface_t* const surface = &emissive_surfaces[emissive_surfaces_count++];
|
||||
surface->model_surface_index = i;
|
||||
surface->surface_index = surface_index;
|
||||
surface->surf = surf;
|
||||
VectorCopy(emissive, surface->emissive);
|
||||
}
|
||||
}
|
||||
|
||||
vk_brush_model_t *const bmodel = mod->cache.data;
|
||||
ASSERT(bmodel);
|
||||
|
||||
if (!is_worldmodel) {
|
||||
if (bmodel->render_model.dynamic_polylights)
|
||||
Mem_Free(bmodel->render_model.dynamic_polylights);
|
||||
bmodel->render_model.dynamic_polylights_count = emissive_surfaces_count;
|
||||
bmodel->render_model.dynamic_polylights = Mem_Malloc(vk_core.pool, sizeof(bmodel->render_model.dynamic_polylights[0]) * emissive_surfaces_count);
|
||||
}
|
||||
|
||||
for (int i = 0; i < emissive_surfaces_count; ++i) {
|
||||
const emissive_surface_t* const s = emissive_surfaces + i;
|
||||
|
||||
const rt_light_add_polygon_t polylight = loadPolyLight(mod, s->surface_index, s->surf, s->emissive);
|
||||
if (!is_worldmodel) {
|
||||
bmodel->render_model.dynamic_polylights[i] = polylight;
|
||||
} else {
|
||||
RT_LightAddPolygon(&polylight);
|
||||
}
|
||||
}
|
||||
|
||||
gEngine.Con_Reportf("Loaded %d polylights for %smodel %s\n", emissive_surfaces_count, is_worldmodel ? "world" : "movable ", mod->name);
|
||||
}
|
||||
|
|
|
@ -11,10 +11,12 @@ struct cl_entity_s;
|
|||
qboolean VK_BrushInit( void );
|
||||
void VK_BrushShutdown( void );
|
||||
|
||||
qboolean VK_BrushModelLoad(struct model_s *mod, qboolean map);
|
||||
qboolean VK_BrushModelLoad(struct model_s *mod);
|
||||
void VK_BrushModelDestroy(struct model_s *mod);
|
||||
|
||||
void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, const matrix4x4 model );
|
||||
void VK_BrushStatsClear( void );
|
||||
|
||||
const texture_t *R_TextureAnimation( const cl_entity_t *ent, const msurface_t *s, const struct texture_s *base_override );
|
||||
|
||||
void R_VkBrushModelCollectEmissiveSurfaces( const struct model_s *mod, qboolean is_worldmodel );
|
||||
|
|
|
@ -467,7 +467,7 @@ static void prepareSurfacesLeafVisibilityCache( const struct model_s *map ) {
|
|||
g_lights_bsp.surfaces[i].potentially_visible_leafs = NULL;
|
||||
}
|
||||
|
||||
void RT_LightsNewMapBegin( const struct model_s *map ) {
|
||||
void RT_LightsNewMap( 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;
|
||||
|
@ -504,48 +504,6 @@ void RT_LightsNewMapBegin( const struct model_s *map ) {
|
|||
g_lights_.visited_cells = bitArrayCreate(g_lights.map.grid_cells);
|
||||
|
||||
prepareSurfacesLeafVisibilityCache( map );
|
||||
|
||||
// Load RAD data based on map name
|
||||
memset(g_lights_.map.emissive_textures, 0, sizeof(g_lights_.map.emissive_textures));
|
||||
loadRadData( map, "maps/lights.rad" );
|
||||
|
||||
{
|
||||
int name_len = Q_strlen(map->name);
|
||||
|
||||
// Strip ".bsp" suffix
|
||||
if (name_len > 4 && 0 == Q_stricmp(map->name + name_len - 4, ".bsp"))
|
||||
name_len -= 4;
|
||||
|
||||
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;
|
||||
cell->frame_sequence = g_lights_.frame_sequence;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RT_LightsFrameBegin( 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;
|
||||
|
||||
g_lights.stats.dirty_cells = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static qboolean addSurfaceLightToCell( int cell_index, int polygon_light_index ) {
|
||||
|
@ -931,10 +889,39 @@ static void processStaticPointLights( void ) {
|
|||
APROF_SCOPE_END(static_lights);
|
||||
}
|
||||
|
||||
void RT_LightsNewMapEnd( const struct model_s *map ) {
|
||||
//debug_dump_lights.enabled = true;
|
||||
void RT_LightsLoadBegin( const struct model_s *map ) {
|
||||
// Load RAD data based on map name
|
||||
{
|
||||
int name_len = Q_strlen(map->name);
|
||||
|
||||
// Strip ".bsp" suffix
|
||||
if (name_len > 4 && 0 == Q_stricmp(map->name + name_len - 4, ".bsp"))
|
||||
name_len -= 4;
|
||||
|
||||
memset(g_lights_.map.emissive_textures, 0, sizeof(g_lights_.map.emissive_textures));
|
||||
loadRadData( map, "maps/lights.rad" );
|
||||
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;
|
||||
cell->frame_sequence = g_lights_.frame_sequence;
|
||||
}
|
||||
}
|
||||
|
||||
processStaticPointLights();
|
||||
}
|
||||
|
||||
void RT_LightsLoadEnd( void ) {
|
||||
//debug_dump_lights.enabled = true;
|
||||
|
||||
// Fix static counts
|
||||
{
|
||||
|
@ -1131,6 +1118,20 @@ int RT_LightAddPolygon(const rt_light_add_polygon_t *addpoly) {
|
|||
}
|
||||
}
|
||||
|
||||
void RT_LightsFrameBegin( 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;
|
||||
|
||||
g_lights.stats.dirty_cells = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static void uploadGridRange( int begin, int end ) {
|
||||
const int count = end - begin;
|
||||
ASSERT( count > 0 );
|
||||
|
|
|
@ -71,9 +71,15 @@ extern vk_lights_t g_lights;
|
|||
qboolean VK_LightsInit( void );
|
||||
void VK_LightsShutdown( void );
|
||||
|
||||
// Allocate clusters and vis data for the new map
|
||||
struct model_s;
|
||||
void RT_LightsNewMapBegin( const struct model_s *map );
|
||||
void RT_LightsNewMapEnd( const struct model_s *map );
|
||||
void RT_LightsNewMap( const struct model_s *map );
|
||||
|
||||
// Clear light data and prepare for loading
|
||||
// RT_LightsNewMap should have been already called for current map
|
||||
void RT_LightsLoadBegin( const struct model_s *map );
|
||||
// Finalize loading light data, i.e. mark everything loaded so far as static light data
|
||||
void RT_LightsLoadEnd( void );
|
||||
|
||||
void RT_LightsFrameBegin( void );
|
||||
void RT_LightsFrameEnd( void );
|
||||
|
|
|
@ -267,6 +267,12 @@ vk_ray_model_t* VK_RayModelCreate( vk_ray_model_init_t args ) {
|
|||
case kVkRenderType_1_1_R: // blend: scr + dst, depth test
|
||||
HACK_additive_emissive = true;
|
||||
break;
|
||||
case kVkRenderTypeSolid:
|
||||
case kVkRenderType_AT:
|
||||
break;
|
||||
case kVkRenderType_COUNT:
|
||||
ASSERT(!"Invalid model render_type");
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < args.model->num_geometries; ++i) {
|
||||
|
@ -539,8 +545,8 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render
|
|||
model->kusochki_updated_this_frame = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < render_model->polylights_count; ++i) {
|
||||
rt_light_add_polygon_t *const polylight = render_model->polylights + i;
|
||||
for (int i = 0; i < render_model->dynamic_polylights_count; ++i) {
|
||||
rt_light_add_polygon_t *const polylight = render_model->dynamic_polylights + i;
|
||||
polylight->transform_row = (const matrix3x4*)transform_row;
|
||||
polylight->dynamic = true;
|
||||
RT_LightAddPolygon(polylight);
|
||||
|
@ -553,8 +559,7 @@ void RT_RayModel_Clear(void) {
|
|||
R_DEBuffer_Init(&g_ray_model_state.kusochki_alloc, MAX_KUSOCHKI / 2, MAX_KUSOCHKI / 2);
|
||||
}
|
||||
|
||||
void XVK_RayModel_ClearForNextFrame( void )
|
||||
{
|
||||
void XVK_RayModel_ClearForNextFrame( void ) {
|
||||
// FIXME we depend on the fact that only a single frame can be in flight
|
||||
// currently framectl waits for the queue to complete before returning
|
||||
// so we can be sure here that previous frame is complete and we're free to
|
||||
|
|
|
@ -662,6 +662,8 @@ qboolean VK_RenderModelInit( vk_render_model_t *model ) {
|
|||
.model = model,
|
||||
};
|
||||
model->ray_model = VK_RayModelCreate(args);
|
||||
model->dynamic_polylights = NULL;
|
||||
model->dynamic_polylights_count = 0;
|
||||
return !!model->ray_model;
|
||||
}
|
||||
|
||||
|
@ -670,8 +672,11 @@ qboolean VK_RenderModelInit( vk_render_model_t *model ) {
|
|||
}
|
||||
|
||||
void VK_RenderModelDestroy( vk_render_model_t* model ) {
|
||||
// FIXME why the condition? we should do the cleanup anyway
|
||||
if (vk_core.rtx && (g_render_state.current_frame_is_ray_traced || !model->dynamic)) {
|
||||
VK_RayModelDestroy(model->ray_model);
|
||||
if (model->dynamic_polylights)
|
||||
Mem_Free(model->dynamic_polylights);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,10 +59,6 @@ typedef struct vk_render_geometry_s {
|
|||
vec3_t emissive;
|
||||
} vk_render_geometry_t;
|
||||
|
||||
struct vk_ray_model_s;
|
||||
|
||||
#define MAX_MODEL_NAME_LENGTH 64
|
||||
|
||||
typedef enum {
|
||||
kVkRenderTypeSolid, // no blending, depth RW
|
||||
kVkRenderType_A_1mA_RW, // blend: src*a + dst*(1-a), depth: RW
|
||||
|
@ -73,11 +69,14 @@ typedef enum {
|
|||
kVkRenderType_1_1_R, // blend: src + dst, depth test
|
||||
kVkRenderType_COUNT
|
||||
} vk_render_type_e;
|
||||
|
||||
struct rt_light_add_polygon_s;
|
||||
struct vk_ray_model_s;
|
||||
|
||||
typedef struct vk_render_model_s {
|
||||
#define MAX_MODEL_NAME_LENGTH 64
|
||||
char debug_name[MAX_MODEL_NAME_LENGTH];
|
||||
|
||||
// FIXME: brushes, sprites, studio models, etc all treat render_mode differently
|
||||
vk_render_type_e render_type;
|
||||
vec4_t color;
|
||||
int lightmap; // <= 0 if no lightmap
|
||||
|
@ -88,13 +87,13 @@ typedef struct vk_render_model_s {
|
|||
// This model will be one-frame only, its buffers are not preserved between frames
|
||||
qboolean dynamic;
|
||||
|
||||
// FIXME ...
|
||||
qboolean static_map;
|
||||
|
||||
// Non-NULL only for ray tracing
|
||||
struct vk_ray_model_s *ray_model;
|
||||
struct rt_light_add_polygon_s *polylights;
|
||||
int polylights_count;
|
||||
|
||||
// Polylights which need to be added per-frame dynamically
|
||||
// Used for non-worldmodel brush models which are not static
|
||||
struct rt_light_add_polygon_s *dynamic_polylights;
|
||||
int dynamic_polylights_count;
|
||||
|
||||
// previous frame ObjectToWorld (model) matrix
|
||||
matrix4x4 prev_transform;
|
||||
|
|
|
@ -82,7 +82,6 @@ static struct {
|
|||
rt_resource_t res[MAX_RESOURCES];
|
||||
|
||||
qboolean reload_pipeline;
|
||||
qboolean reload_lighting;
|
||||
|
||||
matrix4x4 prev_inv_proj, prev_inv_view;
|
||||
} g_rtx = {0};
|
||||
|
@ -140,12 +139,6 @@ void VK_RayFrameBegin( void ) {
|
|||
|
||||
R_PrevFrame_StartFrame();
|
||||
|
||||
// TODO: move all lighting update to scene?
|
||||
if (g_rtx.reload_lighting) {
|
||||
g_rtx.reload_lighting = false;
|
||||
// FIXME temporarily not supported VK_LightsLoadMapStaticLights();
|
||||
}
|
||||
|
||||
// TODO shouldn't we do this in freeze models mode anyway?
|
||||
RT_LightsFrameBegin();
|
||||
}
|
||||
|
@ -601,10 +594,6 @@ static void reloadPipeline( void ) {
|
|||
g_rtx.reload_pipeline = true;
|
||||
}
|
||||
|
||||
static void reloadLighting( void ) {
|
||||
g_rtx.reload_lighting = true;
|
||||
}
|
||||
|
||||
static void freezeModels( void ) {
|
||||
g_ray_model_state.freeze_models = !g_ray_model_state.freeze_models;
|
||||
}
|
||||
|
@ -653,7 +642,6 @@ qboolean VK_RayInit( void )
|
|||
RT_RayModel_Clear();
|
||||
|
||||
gEngine.Cmd_AddCommand("vk_rtx_reload", reloadPipeline, "Reload RTX shader");
|
||||
gEngine.Cmd_AddCommand("vk_rtx_reload_rad", reloadLighting, "Reload RAD files for static lights");
|
||||
gEngine.Cmd_AddCommand("vk_rtx_freeze", freezeModels, "Freeze models, do not update/add/delete models from to-draw list");
|
||||
|
||||
return true;
|
||||
|
|
|
@ -61,6 +61,44 @@ static struct {
|
|||
draw_list_t *draw_list;
|
||||
} g_lists;
|
||||
|
||||
static void loadLights( const model_t *const map ) {
|
||||
RT_LightsLoadBegin(map);
|
||||
|
||||
const int num_models = gEngine.EngineGetParm( PARM_NUMMODELS, 0 );
|
||||
for( int i = 0; i < num_models; i++ ) {
|
||||
const model_t *const mod = gEngine.pfnGetModelByIndex( i + 1 );
|
||||
|
||||
if (!mod)
|
||||
continue;
|
||||
|
||||
if( mod->type != mod_brush )
|
||||
continue;
|
||||
|
||||
const qboolean is_worldmodel = i == 0;
|
||||
R_VkBrushModelCollectEmissiveSurfaces(mod, is_worldmodel);
|
||||
}
|
||||
|
||||
// Load static map lights
|
||||
// Reads surfaces from loaded brush models (must happen after all brushes are loaded)
|
||||
RT_LightsLoadEnd();
|
||||
}
|
||||
|
||||
static void reloadMaterials( void ) {
|
||||
// Materials do affect patching, as new materials can be referenced in patch data
|
||||
// So we must do the full sequence
|
||||
XVK_ParseMapEntities();
|
||||
XVK_ReloadMaterials();
|
||||
XVK_ParseMapPatches();
|
||||
|
||||
// Assumes that the map has been loaded
|
||||
|
||||
// Might have loaded new patch data, need to reload lighting data just in case
|
||||
const model_t *const map = gEngine.pfnGetModelByIndex( 1 );
|
||||
loadLights(map);
|
||||
}
|
||||
|
||||
// Same as the above, but avoids reloading heavy materials data
|
||||
// Only reloads light entities, patches, rad files
|
||||
static void reloadPatches( void ) {
|
||||
// Must re-parse map entities to initialize initial values before patching
|
||||
XVK_ParseMapEntities();
|
||||
|
@ -70,23 +108,8 @@ static void reloadPatches( void ) {
|
|||
// Assumes that the map brush model has been loaded
|
||||
|
||||
// Patching does disturb light sources, reinitialize
|
||||
|
||||
// FIXME loading patches will be broken now ;_;
|
||||
// ?? VK_LightsLoadMapStaticLights();
|
||||
}
|
||||
|
||||
static void reloadMaterials( void ) {
|
||||
// Materials do affect patching, as new materials can be referenced in patch data
|
||||
// So we must do the full sequencce
|
||||
XVK_ParseMapEntities();
|
||||
XVK_ReloadMaterials();
|
||||
XVK_ParseMapPatches();
|
||||
|
||||
// Assumes that the map has been loaded
|
||||
|
||||
// Might have loaded new patch data, need to reload lighting data just in case
|
||||
// FIXME loading patches will be broken now ;_;
|
||||
// ??? VK_LightsLoadMapStaticLights();
|
||||
const model_t *const map = gEngine.pfnGetModelByIndex( 1 );
|
||||
loadLights(map);
|
||||
}
|
||||
|
||||
void VK_SceneInit( void )
|
||||
|
@ -95,9 +118,11 @@ void VK_SceneInit( void )
|
|||
|
||||
g_lists.draw_list = g_lists.draw_stack;
|
||||
g_lists.draw_stack_pos = 0;
|
||||
|
||||
if (vk_core.rtx) {
|
||||
gEngine.Cmd_AddCommand("vk_rtx_reload_materials", reloadMaterials, "Reload PBR materials");
|
||||
gEngine.Cmd_AddCommand("vk_rtx_reload_patches", reloadPatches, "Reload patches (does not update surface deletion)");
|
||||
gEngine.Cmd_AddCommand("vk_rtx_reload_rad", reloadPatches, "Reload RAD files for static lights");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,9 +203,6 @@ void R_NewMap( void ) {
|
|||
// Depends on loaded materials. Must preceed loading brush models.
|
||||
XVK_ParseMapPatches();
|
||||
|
||||
// Need parsed map entities, and also should happen before brush model loading
|
||||
RT_LightsNewMapBegin(map);
|
||||
|
||||
// Load all models at once
|
||||
gEngine.Con_Reportf( "Num models: %d:\n", num_models );
|
||||
for( int i = 0; i < num_models; i++ )
|
||||
|
@ -194,15 +216,12 @@ void R_NewMap( void ) {
|
|||
if( m->type != mod_brush )
|
||||
continue;
|
||||
|
||||
if (!VK_BrushModelLoad(m, i == 0))
|
||||
{
|
||||
gEngine.Con_Printf( S_ERROR "Couldn't load model %s\n", m->name );
|
||||
}
|
||||
if (!VK_BrushModelLoad(m))
|
||||
gEngine.Host_Error( "Couldn't load model %s\n", m->name );
|
||||
}
|
||||
|
||||
// Load static map lights
|
||||
// Reads surfaces from loaded brush models (must happen after all brushes are loaded)
|
||||
RT_LightsNewMapEnd(map);
|
||||
RT_LightsNewMap(map);
|
||||
loadLights(map);
|
||||
|
||||
// TODO should we do something like VK_BrushEndLoad?
|
||||
VK_UploadLightmap();
|
||||
|
|
Loading…
Reference in New Issue