Merge "Enable live reloading light data" #457
- [x] Fixes #417 - [x] Fixes #330 - [x] Fixes #104
This commit is contained in:
commit
d1376a89e4
|
@ -24,6 +24,7 @@
|
||||||
typedef struct vk_brush_model_s {
|
typedef struct vk_brush_model_s {
|
||||||
vk_render_model_t render_model;
|
vk_render_model_t render_model;
|
||||||
int num_water_surfaces;
|
int num_water_surfaces;
|
||||||
|
int *surface_to_geometry_index;
|
||||||
} vk_brush_model_t;
|
} vk_brush_model_t;
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
|
@ -218,6 +219,9 @@ static void EmitWaterPolys( const cl_entity_t *ent, const msurface_t *warp, qboo
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
{
|
{
|
||||||
|
vec3_t emissive;
|
||||||
|
RT_GetEmissiveForTexture(emissive, warp->texinfo->texture->gl_texturenum);
|
||||||
|
|
||||||
const vk_render_geometry_t geometry = {
|
const vk_render_geometry_t geometry = {
|
||||||
.texture = warp->texinfo->texture->gl_texturenum, // FIXME assert >= 0
|
.texture = warp->texinfo->texture->gl_texturenum, // FIXME assert >= 0
|
||||||
.material = kXVkMaterialWater,
|
.material = kXVkMaterialWater,
|
||||||
|
@ -228,6 +232,7 @@ static void EmitWaterPolys( const cl_entity_t *ent, const msurface_t *warp, qboo
|
||||||
|
|
||||||
.element_count = num_indices,
|
.element_count = num_indices,
|
||||||
.index_offset = buffer.indices.unit_offset,
|
.index_offset = buffer.indices.unit_offset,
|
||||||
|
.emissive = {emissive[0], emissive[1], emissive[2]},
|
||||||
};
|
};
|
||||||
|
|
||||||
VK_RenderModelDynamicAddGeometry( &geometry );
|
VK_RenderModelDynamicAddGeometry( &geometry );
|
||||||
|
@ -388,7 +393,7 @@ void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, co
|
||||||
for (int i = 0; i < bmodel->render_model.num_geometries; ++i) {
|
for (int i = 0; i < bmodel->render_model.num_geometries; ++i) {
|
||||||
vk_render_geometry_t *geom = bmodel->render_model.geometries + i;
|
vk_render_geometry_t *geom = bmodel->render_model.geometries + i;
|
||||||
const int surface_index = geom->surf - mod->surfaces;
|
const int surface_index = geom->surf - mod->surfaces;
|
||||||
const xvk_patch_surface_t *patch_surface = g_map_entities.patch.surfaces ? g_map_entities.patch.surfaces+surface_index : NULL;
|
const xvk_patch_surface_t *const patch_surface = R_VkPatchGetSurface(surface_index);
|
||||||
|
|
||||||
if (render_mode == kRenderTransColor) {
|
if (render_mode == kRenderTransColor) {
|
||||||
// TransColor mode means no texture color is used
|
// TransColor mode means no texture color is used
|
||||||
|
@ -427,9 +432,12 @@ static qboolean renderableSurface( const msurface_t *surf, int i ) {
|
||||||
// PRINTFLAGS(PRINTFLAG)
|
// PRINTFLAGS(PRINTFLAG)
|
||||||
// gEngine.Con_Reportf("\n");
|
// gEngine.Con_Reportf("\n");
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
if (g_map_entities.patch.surfaces && g_map_entities.patch.surfaces[i].flags & Patch_Surface_Delete)
|
{
|
||||||
return false;
|
const xvk_patch_surface_t *patch_surface = R_VkPatchGetSurface(i);
|
||||||
|
if (patch_surface && patch_surface->flags & Patch_Surface_Delete)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//if( surf->flags & ( SURF_DRAWSKY | SURF_DRAWTURB | SURF_CONVEYOR | SURF_DRAWTURB_QUADS ) ) {
|
//if( surf->flags & ( SURF_DRAWSKY | SURF_DRAWTURB | SURF_CONVEYOR | SURF_DRAWTURB_QUADS ) ) {
|
||||||
if( surf->flags & ( SURF_DRAWTURB | SURF_DRAWTURB_QUADS ) ) {
|
if( surf->flags & ( SURF_DRAWTURB | SURF_DRAWTURB_QUADS ) ) {
|
||||||
|
@ -456,8 +464,6 @@ typedef struct {
|
||||||
int num_surfaces, num_vertices, num_indices;
|
int num_surfaces, num_vertices, num_indices;
|
||||||
int max_texture_id;
|
int max_texture_id;
|
||||||
int water_surfaces;
|
int water_surfaces;
|
||||||
//int sky_surfaces;
|
|
||||||
int emissive_surfaces;
|
|
||||||
} model_sizes_t;
|
} model_sizes_t;
|
||||||
|
|
||||||
static model_sizes_t computeSizes( const model_t *mod ) {
|
static model_sizes_t computeSizes( const model_t *mod ) {
|
||||||
|
@ -479,39 +485,11 @@ static model_sizes_t computeSizes( const model_t *mod ) {
|
||||||
sizes.num_indices += 3 * (surf->numedges - 1);
|
sizes.num_indices += 3 * (surf->numedges - 1);
|
||||||
if (tex_id > sizes.max_texture_id)
|
if (tex_id > sizes.max_texture_id)
|
||||||
sizes.max_texture_id = tex_id;
|
sizes.max_texture_id = tex_id;
|
||||||
|
|
||||||
{
|
|
||||||
const xvk_patch_surface_t *const psurf = g_map_entities.patch.surfaces ? g_map_entities.patch.surfaces + surface_index : NULL;
|
|
||||||
vec3_t emissive;
|
|
||||||
if ((psurf && (psurf->flags & Patch_Surface_Emissive)) || (RT_GetEmissiveForTexture(emissive, tex_id)))
|
|
||||||
++sizes.emissive_surfaces;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sizes;
|
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 ) {
|
static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
|
||||||
vk_brush_model_t *bmodel = mod->cache.data;
|
vk_brush_model_t *bmodel = mod->cache.data;
|
||||||
uint32_t vertex_offset = 0;
|
uint32_t vertex_offset = 0;
|
||||||
|
@ -545,7 +523,7 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
|
||||||
int index_count = 0;
|
int index_count = 0;
|
||||||
vec3_t tangent;
|
vec3_t tangent;
|
||||||
int tex_id = surf->texinfo->texture->gl_texturenum;
|
int tex_id = surf->texinfo->texture->gl_texturenum;
|
||||||
const xvk_patch_surface_t *const psurf = g_map_entities.patch.surfaces ? g_map_entities.patch.surfaces + surface_index : NULL;
|
const xvk_patch_surface_t *const psurf = R_VkPatchGetSurface(i);
|
||||||
|
|
||||||
if (!renderableSurface(surf, surface_index))
|
if (!renderableSurface(surf, surface_index))
|
||||||
continue;
|
continue;
|
||||||
|
@ -553,29 +531,7 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
|
||||||
if (t != tex_id)
|
if (t != tex_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// FIXME move this to rt_light_bsp and static loading
|
bmodel->surface_to_geometry_index[i] = num_geometries;
|
||||||
{
|
|
||||||
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;
|
++num_geometries;
|
||||||
|
|
||||||
|
@ -588,6 +544,8 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VectorClear(model_geometry->emissive);
|
||||||
|
|
||||||
model_geometry->surf = surf;
|
model_geometry->surf = surf;
|
||||||
model_geometry->texture = tex_id;
|
model_geometry->texture = tex_id;
|
||||||
|
|
||||||
|
@ -677,10 +635,8 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
|
||||||
|
|
||||||
R_GeometryBufferUnlock( &buffer );
|
R_GeometryBufferUnlock( &buffer );
|
||||||
|
|
||||||
if (bmodel->render_model.polylights) {
|
bmodel->render_model.dynamic_polylights = NULL;
|
||||||
gEngine.Con_Reportf("Dynamic polylights %d %d \n", sizes.emissive_surfaces, bmodel->render_model.polylights_count);
|
bmodel->render_model.dynamic_polylights_count = 0;
|
||||||
ASSERT(sizes.emissive_surfaces == bmodel->render_model.polylights_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(sizes.num_surfaces == num_geometries);
|
ASSERT(sizes.num_surfaces == num_geometries);
|
||||||
bmodel->render_model.num_geometries = num_geometries;
|
bmodel->render_model.num_geometries = num_geometries;
|
||||||
|
@ -688,10 +644,8 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
qboolean VK_BrushModelLoad( model_t *mod, qboolean map )
|
qboolean VK_BrushModelLoad( model_t *mod ) {
|
||||||
{
|
if (mod->cache.data) {
|
||||||
if (mod->cache.data)
|
|
||||||
{
|
|
||||||
gEngine.Con_Reportf( S_WARN "Model %s was already loaded\n", mod->name );
|
gEngine.Con_Reportf( S_WARN "Model %s was already loaded\n", mod->name );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -702,22 +656,20 @@ qboolean VK_BrushModelLoad( model_t *mod, qboolean map )
|
||||||
const model_sizes_t sizes = computeSizes( mod );
|
const model_sizes_t sizes = computeSizes( mod );
|
||||||
const size_t model_size =
|
const size_t model_size =
|
||||||
sizeof(vk_brush_model_t) +
|
sizeof(vk_brush_model_t) +
|
||||||
sizeof(vk_render_geometry_t) * sizes.num_surfaces;
|
sizeof(vk_render_geometry_t) * sizes.num_surfaces +
|
||||||
|
sizeof(int) * mod->nummodelsurfaces;
|
||||||
|
|
||||||
vk_brush_model_t *bmodel = Mem_Calloc(vk_core.pool, model_size);
|
vk_brush_model_t *bmodel = Mem_Calloc(vk_core.pool, model_size);
|
||||||
mod->cache.data = bmodel;
|
mod->cache.data = bmodel;
|
||||||
Q_strncpy(bmodel->render_model.debug_name, mod->name, sizeof(bmodel->render_model.debug_name));
|
Q_strncpy(bmodel->render_model.debug_name, mod->name, sizeof(bmodel->render_model.debug_name));
|
||||||
bmodel->render_model.render_type = kVkRenderTypeSolid;
|
bmodel->render_model.render_type = kVkRenderTypeSolid;
|
||||||
bmodel->render_model.static_map = map;
|
|
||||||
|
|
||||||
bmodel->num_water_surfaces = sizes.water_surfaces;
|
bmodel->num_water_surfaces = sizes.water_surfaces;
|
||||||
Vector4Set(bmodel->render_model.color, 1, 1, 1, 1);
|
Vector4Set(bmodel->render_model.color, 1, 1, 1, 1);
|
||||||
|
|
||||||
if (sizes.num_surfaces != 0) {
|
if (sizes.num_surfaces != 0) {
|
||||||
bmodel->render_model.geometries = (vk_render_geometry_t*)((char*)(bmodel + 1));
|
bmodel->render_model.geometries = (vk_render_geometry_t*)((char*)(bmodel + 1));
|
||||||
|
bmodel->surface_to_geometry_index = (int*)((char*)(bmodel->render_model.geometries + sizes.num_surfaces));
|
||||||
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)) {
|
if (!loadBrushSurfaces(sizes, mod) || !VK_RenderModelInit(&bmodel->render_model)) {
|
||||||
gEngine.Con_Printf(S_ERROR "Could not load model %s\n", mod->name);
|
gEngine.Con_Printf(S_ERROR "Could not load model %s\n", mod->name);
|
||||||
|
@ -742,8 +694,6 @@ void VK_BrushModelDestroy( model_t *mod ) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
VK_RenderModelDestroy(&bmodel->render_model);
|
VK_RenderModelDestroy(&bmodel->render_model);
|
||||||
if (bmodel->render_model.polylights)
|
|
||||||
Mem_Free(bmodel->render_model.polylights);
|
|
||||||
Mem_Free(bmodel);
|
Mem_Free(bmodel);
|
||||||
mod->cache.data = NULL;
|
mod->cache.data = NULL;
|
||||||
}
|
}
|
||||||
|
@ -754,3 +704,106 @@ void VK_BrushStatsClear( void )
|
||||||
g_brush.stat.num_vertices = 0;
|
g_brush.stat.num_vertices = 0;
|
||||||
g_brush.stat.num_indices = 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;
|
||||||
|
|
||||||
|
// Load list of all emissive surfaces
|
||||||
|
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?
|
||||||
|
|
||||||
|
vec3_t emissive;
|
||||||
|
const xvk_patch_surface_t *const psurf = R_VkPatchGetSurface(surface_index);
|
||||||
|
if (psurf && (psurf->flags & Patch_Surface_Emissive)) {
|
||||||
|
VectorCopy(psurf->emissive, emissive);
|
||||||
|
} else if (RT_GetEmissiveForTexture(emissive, tex_id)) {
|
||||||
|
// emissive
|
||||||
|
} else {
|
||||||
|
// not emissive, continue to the next
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//gEngine.Con_Reportf("%d: i=%d surf_index=%d patch=%d(%#x) => emissive=(%f,%f,%f)\n", emissive_surfaces_count, i, surface_index, !!psurf, psurf?psurf->flags:0, emissive[0], emissive[1], emissive[2]);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Clear old per-geometry emissive values. The new emissive values will be assigned by the loop below only to the relevant geoms
|
||||||
|
for (int i = 0; i < bmodel->render_model.num_geometries; ++i) {
|
||||||
|
vk_render_geometry_t *const geom = bmodel->render_model.geometries + i;
|
||||||
|
VectorClear(geom->emissive);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-worldmodel brush models may move around and so must have their emissive surfaces treated as dynamic
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply all emissive surfaces found
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Worldmodel emissive surfaces are added immediately, as the worldmodel is always drawn and is static.
|
||||||
|
// Non-worldmodel ones will be applied later when the model is actually rendered
|
||||||
|
if (is_worldmodel) {
|
||||||
|
RT_LightAddPolygon(&polylight);
|
||||||
|
} else {
|
||||||
|
bmodel->render_model.dynamic_polylights[i] = polylight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign the emissive value to the right geometry
|
||||||
|
VectorCopy(polylight.emissive, bmodel->render_model.geometries[bmodel->surface_to_geometry_index[s->model_surface_index]].emissive);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 );
|
qboolean VK_BrushInit( void );
|
||||||
void VK_BrushShutdown( 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_BrushModelDestroy(struct model_s *mod);
|
||||||
|
|
||||||
void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, const matrix4x4 model );
|
void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, const matrix4x4 model );
|
||||||
void VK_BrushStatsClear( void );
|
void VK_BrushStatsClear( void );
|
||||||
|
|
||||||
const texture_t *R_TextureAnimation( const cl_entity_t *ent, const msurface_t *s, const struct texture_s *base_override );
|
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;
|
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?)
|
// 1. Determine map bounding box (and optimal grid size?)
|
||||||
// map->mins, maxs
|
// map->mins, maxs
|
||||||
vec3_t map_size, min_cell, max_cell;
|
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);
|
g_lights_.visited_cells = bitArrayCreate(g_lights.map.grid_cells);
|
||||||
|
|
||||||
prepareSurfacesLeafVisibilityCache( map );
|
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 ) {
|
static qboolean addSurfaceLightToCell( int cell_index, int polygon_light_index ) {
|
||||||
|
@ -931,10 +889,39 @@ static void processStaticPointLights( void ) {
|
||||||
APROF_SCOPE_END(static_lights);
|
APROF_SCOPE_END(static_lights);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RT_LightsNewMapEnd( const struct model_s *map ) {
|
void RT_LightsLoadBegin( const struct model_s *map ) {
|
||||||
//debug_dump_lights.enabled = true;
|
// 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();
|
processStaticPointLights();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RT_LightsLoadEnd( void ) {
|
||||||
|
//debug_dump_lights.enabled = true;
|
||||||
|
|
||||||
// Fix static counts
|
// 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 ) {
|
static void uploadGridRange( int begin, int end ) {
|
||||||
const int count = end - begin;
|
const int count = end - begin;
|
||||||
ASSERT( count > 0 );
|
ASSERT( count > 0 );
|
||||||
|
|
|
@ -71,9 +71,15 @@ extern vk_lights_t g_lights;
|
||||||
qboolean VK_LightsInit( void );
|
qboolean VK_LightsInit( void );
|
||||||
void VK_LightsShutdown( void );
|
void VK_LightsShutdown( void );
|
||||||
|
|
||||||
|
// Allocate clusters and vis data for the new map
|
||||||
struct model_s;
|
struct model_s;
|
||||||
void RT_LightsNewMapBegin( const struct model_s *map );
|
void RT_LightsNewMap( const struct model_s *map );
|
||||||
void RT_LightsNewMapEnd( 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_LightsFrameBegin( void );
|
||||||
void RT_LightsFrameEnd( void );
|
void RT_LightsFrameEnd( void );
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
|
|
||||||
xvk_map_entities_t g_map_entities;
|
xvk_map_entities_t g_map_entities;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
xvk_patch_surface_t *surfaces;
|
||||||
|
int surfaces_count;
|
||||||
|
} g_patch;
|
||||||
|
|
||||||
static unsigned parseEntPropWadList(const char* value, string *out, unsigned bit) {
|
static unsigned parseEntPropWadList(const char* value, string *out, unsigned bit) {
|
||||||
int dst_left = sizeof(string) - 2; // ; \0
|
int dst_left = sizeof(string) - 2; // ; \0
|
||||||
char *dst = *out;
|
char *dst = *out;
|
||||||
|
@ -321,16 +326,17 @@ static void addPatchSurface( const entity_props_t *props, uint32_t have_fields )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_map_entities.patch.surfaces) {
|
if (!g_patch.surfaces) {
|
||||||
g_map_entities.patch.surfaces = Mem_Malloc(vk_core.pool, num_surfaces * sizeof(xvk_patch_surface_t));
|
g_patch.surfaces = Mem_Malloc(vk_core.pool, num_surfaces * sizeof(xvk_patch_surface_t));
|
||||||
|
g_patch.surfaces_count = num_surfaces;
|
||||||
for (int i = 0; i < num_surfaces; ++i) {
|
for (int i = 0; i < num_surfaces; ++i) {
|
||||||
g_map_entities.patch.surfaces[i].flags = Patch_Surface_NoPatch;
|
g_patch.surfaces[i].flags = Patch_Surface_NoPatch;
|
||||||
g_map_entities.patch.surfaces[i].tex_id = -1;
|
g_patch.surfaces[i].tex_id = -1;
|
||||||
g_map_entities.patch.surfaces[i].tex = NULL;
|
g_patch.surfaces[i].tex = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
psurf = g_map_entities.patch.surfaces + index;
|
psurf = g_patch.surfaces + index;
|
||||||
|
|
||||||
if (should_remove) {
|
if (should_remove) {
|
||||||
gEngine.Con_Reportf("Patch: surface %d removed\n", index);
|
gEngine.Con_Reportf("Patch: surface %d removed\n", index);
|
||||||
|
@ -507,9 +513,10 @@ static void parsePatches( const model_t *const map ) {
|
||||||
char filename[256];
|
char filename[256];
|
||||||
byte *data;
|
byte *data;
|
||||||
|
|
||||||
if (g_map_entities.patch.surfaces) {
|
if (g_patch.surfaces) {
|
||||||
Mem_Free(g_map_entities.patch.surfaces);
|
Mem_Free(g_patch.surfaces);
|
||||||
g_map_entities.patch.surfaces = NULL;
|
g_patch.surfaces = NULL;
|
||||||
|
g_patch.surfaces_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_snprintf(filename, sizeof(filename), "luchiki/%s.patch", map->name);
|
Q_snprintf(filename, sizeof(filename), "luchiki/%s.patch", map->name);
|
||||||
|
@ -544,3 +551,14 @@ void XVK_ParseMapPatches( void ) {
|
||||||
parsePatches( map );
|
parsePatches( map );
|
||||||
orientSpotlights();
|
orientSpotlights();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const xvk_patch_surface_t* R_VkPatchGetSurface( int surface_index ) {
|
||||||
|
if (!g_patch.surfaces_count)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ASSERT(g_patch.surfaces);
|
||||||
|
ASSERT(surface_index >= 0);
|
||||||
|
ASSERT(surface_index < g_patch.surfaces_count);
|
||||||
|
|
||||||
|
return g_patch.surfaces + surface_index;
|
||||||
|
}
|
||||||
|
|
|
@ -72,6 +72,28 @@ typedef struct {
|
||||||
vec3_t origin;
|
vec3_t origin;
|
||||||
} xvk_mapent_target_t;
|
} xvk_mapent_target_t;
|
||||||
|
|
||||||
|
#define MAX_MAPENT_TARGETS 256
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int num_lights;
|
||||||
|
vk_light_entity_t lights[256];
|
||||||
|
|
||||||
|
int single_environment_index;
|
||||||
|
int entity_count;
|
||||||
|
|
||||||
|
string wadlist;
|
||||||
|
|
||||||
|
int num_targets;
|
||||||
|
xvk_mapent_target_t targets[MAX_MAPENT_TARGETS];
|
||||||
|
} xvk_map_entities_t;
|
||||||
|
|
||||||
|
extern xvk_map_entities_t g_map_entities;
|
||||||
|
|
||||||
|
enum { NoEnvironmentLights = -1, MoreThanOneEnvironmentLight = -2 };
|
||||||
|
|
||||||
|
void XVK_ParseMapEntities( void );
|
||||||
|
void XVK_ParseMapPatches( void );
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
Patch_Surface_NoPatch = 0,
|
Patch_Surface_NoPatch = 0,
|
||||||
Patch_Surface_Delete = 0x01,
|
Patch_Surface_Delete = 0x01,
|
||||||
|
@ -93,30 +115,5 @@ typedef struct {
|
||||||
vec3_t emissive;
|
vec3_t emissive;
|
||||||
} xvk_patch_surface_t;
|
} xvk_patch_surface_t;
|
||||||
|
|
||||||
typedef struct {
|
const xvk_patch_surface_t* R_VkPatchGetSurface( int surface_index );
|
||||||
xvk_patch_surface_t *surfaces;
|
|
||||||
} xvk_patch_t;
|
|
||||||
|
|
||||||
#define MAX_MAPENT_TARGETS 256
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int num_lights;
|
|
||||||
vk_light_entity_t lights[256];
|
|
||||||
|
|
||||||
int single_environment_index;
|
|
||||||
int entity_count;
|
|
||||||
|
|
||||||
string wadlist;
|
|
||||||
|
|
||||||
int num_targets;
|
|
||||||
xvk_mapent_target_t targets[MAX_MAPENT_TARGETS];
|
|
||||||
|
|
||||||
xvk_patch_t patch;
|
|
||||||
} xvk_map_entities_t;
|
|
||||||
|
|
||||||
extern xvk_map_entities_t g_map_entities;
|
|
||||||
|
|
||||||
enum { NoEnvironmentLights = -1, MoreThanOneEnvironmentLight = -2 };
|
|
||||||
|
|
||||||
void XVK_ParseMapEntities( void );
|
|
||||||
void XVK_ParseMapPatches( void );
|
|
||||||
|
|
|
@ -164,9 +164,6 @@ static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometr
|
||||||
kusok->index_offset = geom->index_offset;
|
kusok->index_offset = geom->index_offset;
|
||||||
kusok->triangles = geom->element_count / 3;
|
kusok->triangles = geom->element_count / 3;
|
||||||
|
|
||||||
/* if (!render_model->static_map) */
|
|
||||||
/* VK_LightsAddEmissiveSurface( geom, transform_row, false ); */
|
|
||||||
|
|
||||||
kusok->tex_base_color = mat->tex_base_color;
|
kusok->tex_base_color = mat->tex_base_color;
|
||||||
kusok->tex_roughness = mat->tex_roughness;
|
kusok->tex_roughness = mat->tex_roughness;
|
||||||
kusok->tex_metalness = mat->tex_metalness;
|
kusok->tex_metalness = mat->tex_metalness;
|
||||||
|
@ -200,11 +197,7 @@ static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometr
|
||||||
Vector4Copy(gcolor, kusok->color);
|
Vector4Copy(gcolor, kusok->color);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (geom->material == kXVkMaterialEmissive || geom->material == kXVkMaterialEmissiveGlow) {
|
VectorCopy(geom->emissive, kusok->emissive);
|
||||||
VectorCopy(geom->emissive, kusok->emissive);
|
|
||||||
} else {
|
|
||||||
RT_GetEmissiveForTexture( kusok->emissive, geom->texture );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME these should be done in a different way
|
/* FIXME these should be done in a different way
|
||||||
if (geom->material == kXVkMaterialConveyor) {
|
if (geom->material == kXVkMaterialConveyor) {
|
||||||
|
@ -267,6 +260,12 @@ vk_ray_model_t* VK_RayModelCreate( vk_ray_model_init_t args ) {
|
||||||
case kVkRenderType_1_1_R: // blend: scr + dst, depth test
|
case kVkRenderType_1_1_R: // blend: scr + dst, depth test
|
||||||
HACK_additive_emissive = true;
|
HACK_additive_emissive = true;
|
||||||
break;
|
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) {
|
for (int i = 0; i < args.model->num_geometries; ++i) {
|
||||||
|
@ -539,8 +538,8 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render
|
||||||
model->kusochki_updated_this_frame = true;
|
model->kusochki_updated_this_frame = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < render_model->polylights_count; ++i) {
|
for (int i = 0; i < render_model->dynamic_polylights_count; ++i) {
|
||||||
rt_light_add_polygon_t *const polylight = render_model->polylights + i;
|
rt_light_add_polygon_t *const polylight = render_model->dynamic_polylights + i;
|
||||||
polylight->transform_row = (const matrix3x4*)transform_row;
|
polylight->transform_row = (const matrix3x4*)transform_row;
|
||||||
polylight->dynamic = true;
|
polylight->dynamic = true;
|
||||||
RT_LightAddPolygon(polylight);
|
RT_LightAddPolygon(polylight);
|
||||||
|
@ -553,8 +552,7 @@ void RT_RayModel_Clear(void) {
|
||||||
R_DEBuffer_Init(&g_ray_model_state.kusochki_alloc, MAX_KUSOCHKI / 2, MAX_KUSOCHKI / 2);
|
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
|
// 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
|
// 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
|
// 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 = model,
|
||||||
};
|
};
|
||||||
model->ray_model = VK_RayModelCreate(args);
|
model->ray_model = VK_RayModelCreate(args);
|
||||||
|
model->dynamic_polylights = NULL;
|
||||||
|
model->dynamic_polylights_count = 0;
|
||||||
return !!model->ray_model;
|
return !!model->ray_model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,8 +672,11 @@ qboolean VK_RenderModelInit( vk_render_model_t *model ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VK_RenderModelDestroy( 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)) {
|
if (vk_core.rtx && (g_render_state.current_frame_is_ray_traced || !model->dynamic)) {
|
||||||
VK_RayModelDestroy(model->ray_model);
|
VK_RayModelDestroy(model->ray_model);
|
||||||
|
if (model->dynamic_polylights)
|
||||||
|
Mem_Free(model->dynamic_polylights);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ typedef enum {
|
||||||
kXVkMaterialChrome,
|
kXVkMaterialChrome,
|
||||||
} XVkMaterialType;
|
} XVkMaterialType;
|
||||||
|
|
||||||
typedef struct vk_render_geometry_s {
|
typedef struct vk_render_geometry_s {
|
||||||
int index_offset, vertex_offset;
|
int index_offset, vertex_offset;
|
||||||
|
|
||||||
// Animated textures will be dynamic and change between frames
|
// Animated textures will be dynamic and change between frames
|
||||||
|
@ -55,14 +55,10 @@ typedef struct vk_render_geometry_s {
|
||||||
// - updating dynamic lights (TODO: can decouple from surface/brush models by providing texture_id and aabb directly here)
|
// - updating dynamic lights (TODO: can decouple from surface/brush models by providing texture_id and aabb directly here)
|
||||||
const struct msurface_s *surf;
|
const struct msurface_s *surf;
|
||||||
|
|
||||||
// for kXVkMaterialEmissive
|
// for kXVkMaterialEmissive{,Glow} and others
|
||||||
vec3_t emissive;
|
vec3_t emissive;
|
||||||
} vk_render_geometry_t;
|
} vk_render_geometry_t;
|
||||||
|
|
||||||
struct vk_ray_model_s;
|
|
||||||
|
|
||||||
#define MAX_MODEL_NAME_LENGTH 64
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
kVkRenderTypeSolid, // no blending, depth RW
|
kVkRenderTypeSolid, // no blending, depth RW
|
||||||
kVkRenderType_A_1mA_RW, // blend: src*a + dst*(1-a), 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_1_1_R, // blend: src + dst, depth test
|
||||||
kVkRenderType_COUNT
|
kVkRenderType_COUNT
|
||||||
} vk_render_type_e;
|
} vk_render_type_e;
|
||||||
|
|
||||||
struct rt_light_add_polygon_s;
|
struct rt_light_add_polygon_s;
|
||||||
|
struct vk_ray_model_s;
|
||||||
|
|
||||||
typedef struct vk_render_model_s {
|
typedef struct vk_render_model_s {
|
||||||
|
#define MAX_MODEL_NAME_LENGTH 64
|
||||||
char debug_name[MAX_MODEL_NAME_LENGTH];
|
char debug_name[MAX_MODEL_NAME_LENGTH];
|
||||||
|
|
||||||
// FIXME: brushes, sprites, studio models, etc all treat render_mode differently
|
|
||||||
vk_render_type_e render_type;
|
vk_render_type_e render_type;
|
||||||
vec4_t color;
|
vec4_t color;
|
||||||
int lightmap; // <= 0 if no lightmap
|
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
|
// This model will be one-frame only, its buffers are not preserved between frames
|
||||||
qboolean dynamic;
|
qboolean dynamic;
|
||||||
|
|
||||||
// FIXME ...
|
|
||||||
qboolean static_map;
|
|
||||||
|
|
||||||
// Non-NULL only for ray tracing
|
// Non-NULL only for ray tracing
|
||||||
struct vk_ray_model_s *ray_model;
|
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
|
// previous frame ObjectToWorld (model) matrix
|
||||||
matrix4x4 prev_transform;
|
matrix4x4 prev_transform;
|
||||||
|
|
|
@ -82,7 +82,6 @@ static struct {
|
||||||
rt_resource_t res[MAX_RESOURCES];
|
rt_resource_t res[MAX_RESOURCES];
|
||||||
|
|
||||||
qboolean reload_pipeline;
|
qboolean reload_pipeline;
|
||||||
qboolean reload_lighting;
|
|
||||||
|
|
||||||
matrix4x4 prev_inv_proj, prev_inv_view;
|
matrix4x4 prev_inv_proj, prev_inv_view;
|
||||||
} g_rtx = {0};
|
} g_rtx = {0};
|
||||||
|
@ -140,12 +139,6 @@ void VK_RayFrameBegin( void ) {
|
||||||
|
|
||||||
R_PrevFrame_StartFrame();
|
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?
|
// TODO shouldn't we do this in freeze models mode anyway?
|
||||||
RT_LightsFrameBegin();
|
RT_LightsFrameBegin();
|
||||||
}
|
}
|
||||||
|
@ -601,10 +594,6 @@ static void reloadPipeline( void ) {
|
||||||
g_rtx.reload_pipeline = true;
|
g_rtx.reload_pipeline = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reloadLighting( void ) {
|
|
||||||
g_rtx.reload_lighting = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void freezeModels( void ) {
|
static void freezeModels( void ) {
|
||||||
g_ray_model_state.freeze_models = !g_ray_model_state.freeze_models;
|
g_ray_model_state.freeze_models = !g_ray_model_state.freeze_models;
|
||||||
}
|
}
|
||||||
|
@ -653,7 +642,6 @@ qboolean VK_RayInit( void )
|
||||||
RT_RayModel_Clear();
|
RT_RayModel_Clear();
|
||||||
|
|
||||||
gEngine.Cmd_AddCommand("vk_rtx_reload", reloadPipeline, "Reload RTX shader");
|
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");
|
gEngine.Cmd_AddCommand("vk_rtx_freeze", freezeModels, "Freeze models, do not update/add/delete models from to-draw list");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -61,6 +61,44 @@ static struct {
|
||||||
draw_list_t *draw_list;
|
draw_list_t *draw_list;
|
||||||
} g_lists;
|
} 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 ) {
|
static void reloadPatches( void ) {
|
||||||
// Must re-parse map entities to initialize initial values before patching
|
// Must re-parse map entities to initialize initial values before patching
|
||||||
XVK_ParseMapEntities();
|
XVK_ParseMapEntities();
|
||||||
|
@ -70,23 +108,8 @@ static void reloadPatches( void ) {
|
||||||
// Assumes that the map brush model has been loaded
|
// Assumes that the map brush model has been loaded
|
||||||
|
|
||||||
// Patching does disturb light sources, reinitialize
|
// Patching does disturb light sources, reinitialize
|
||||||
|
const model_t *const map = gEngine.pfnGetModelByIndex( 1 );
|
||||||
// FIXME loading patches will be broken now ;_;
|
loadLights(map);
|
||||||
// ?? 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VK_SceneInit( void )
|
void VK_SceneInit( void )
|
||||||
|
@ -95,9 +118,11 @@ void VK_SceneInit( void )
|
||||||
|
|
||||||
g_lists.draw_list = g_lists.draw_stack;
|
g_lists.draw_list = g_lists.draw_stack;
|
||||||
g_lists.draw_stack_pos = 0;
|
g_lists.draw_stack_pos = 0;
|
||||||
|
|
||||||
if (vk_core.rtx) {
|
if (vk_core.rtx) {
|
||||||
gEngine.Cmd_AddCommand("vk_rtx_reload_materials", reloadMaterials, "Reload PBR materials");
|
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_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.
|
// Depends on loaded materials. Must preceed loading brush models.
|
||||||
XVK_ParseMapPatches();
|
XVK_ParseMapPatches();
|
||||||
|
|
||||||
// Need parsed map entities, and also should happen before brush model loading
|
|
||||||
RT_LightsNewMapBegin(map);
|
|
||||||
|
|
||||||
// Load all models at once
|
// Load all models at once
|
||||||
gEngine.Con_Reportf( "Num models: %d:\n", num_models );
|
gEngine.Con_Reportf( "Num models: %d:\n", num_models );
|
||||||
for( int i = 0; i < num_models; i++ )
|
for( int i = 0; i < num_models; i++ )
|
||||||
|
@ -194,15 +216,12 @@ void R_NewMap( void ) {
|
||||||
if( m->type != mod_brush )
|
if( m->type != mod_brush )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!VK_BrushModelLoad(m, i == 0))
|
if (!VK_BrushModelLoad(m))
|
||||||
{
|
gEngine.Host_Error( "Couldn't load model %s\n", m->name );
|
||||||
gEngine.Con_Printf( S_ERROR "Couldn't load model %s\n", m->name );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load static map lights
|
RT_LightsNewMap(map);
|
||||||
// Reads surfaces from loaded brush models (must happen after all brushes are loaded)
|
loadLights(map);
|
||||||
RT_LightsNewMapEnd(map);
|
|
||||||
|
|
||||||
// TODO should we do something like VK_BrushEndLoad?
|
// TODO should we do something like VK_BrushEndLoad?
|
||||||
VK_UploadLightmap();
|
VK_UploadLightmap();
|
||||||
|
|
|
@ -2021,6 +2021,8 @@ static void R_StudioDrawNormalMesh( short *ptricmds, vec3_t *pstudionorms, float
|
||||||
|
|
||||||
.index_offset = buffer.indices.unit_offset,
|
.index_offset = buffer.indices.unit_offset,
|
||||||
.element_count = num_indices,
|
.element_count = num_indices,
|
||||||
|
|
||||||
|
.emissive = {0, 0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
VK_RenderModelDynamicAddGeometry( &geometry );
|
VK_RenderModelDynamicAddGeometry( &geometry );
|
||||||
|
|
Loading…
Reference in New Issue