rt: add moving polygon lights support

This commit is contained in:
Ivan Avdeev 2022-02-02 21:32:10 -08:00
parent f9bf0aadd0
commit 3a6bed136a
6 changed files with 91 additions and 38 deletions

View File

@ -283,7 +283,7 @@ void sampleEmissiveSurfaces(vec3 P, vec3 N, vec3 throughput, vec3 view_dir, Mate
#elif DO_ALL_IN_CLUSTER
const SampleContext ctx = buildSampleContext(P, N, view_dir);
const uint num_polygons = min(128, uint(light_grid.clusters[cluster_index].num_polygons));
const uint num_polygons = uint(light_grid.clusters[cluster_index].num_polygons);
for (uint i = 0; i < num_polygons; ++i) {
const uint index = uint(light_grid.clusters[cluster_index].polygons[i]);
const PolygonLight poly = lights.polygons[index];

View File

@ -19,6 +19,14 @@
#include <math.h>
#include <memory.h>
typedef struct vk_brush_model_s {
vk_render_model_t render_model;
int num_water_surfaces;
rt_light_add_polygon_t *polylights;
int polylights_count;
} vk_brush_model_t;
static struct {
struct {
int num_vertices, num_indices;
@ -326,7 +334,7 @@ const texture_t *R_TextureAnimation( const cl_entity_t *ent, const msurface_t *s
return base;
}
void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode )
void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, const matrix4x4 model )
{
// Expect all buffers to be bound
const model_t *mod = ent->model;
@ -344,6 +352,13 @@ void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode )
if (bmodel->render_model.num_geometries == 0)
return;
for (int i = 0; i < bmodel->polylights_count; ++i) {
rt_light_add_polygon_t *polylight = bmodel->polylights + i;
polylight->transform_row = (const matrix3x4*)model;
polylight->dynamic = true;
RT_LightAddPolygon(polylight);
}
for (int i = 0; i < bmodel->render_model.num_geometries; ++i) {
vk_render_geometry_t *geom = bmodel->render_model.geometries + i;
const int surface_index = geom->surf - mod->surfaces;
@ -413,6 +428,7 @@ typedef struct {
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 ) {
@ -422,6 +438,7 @@ static model_sizes_t computeSizes( const model_t *mod ) {
{
const int surface_index = mod->firstmodelsurface + i;
const msurface_t *surf = mod->surfaces + surface_index;
const int tex_id = surf->texinfo->texture->gl_texturenum;
sizes.water_surfaces += !!(surf->flags & (SURF_DRAWTURB | SURF_DRAWTURB_QUADS));
@ -431,15 +448,22 @@ static model_sizes_t computeSizes( const model_t *mod ) {
++sizes.num_surfaces;
sizes.num_vertices += surf->numedges;
sizes.num_indices += 3 * (surf->numedges - 1);
if (surf->texinfo->texture->gl_texturenum > sizes.max_texture_id)
sizes.max_texture_id = surf->texinfo->texture->gl_texturenum;
if (tex_id > sizes.max_texture_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;
}
static void loadEmissiveSurface(const model_t *mod, const int surface_index, const msurface_t *surf, const vec3_t emissive) {
rt_light_add_polygon_t lpoly;
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
@ -456,7 +480,7 @@ static void loadEmissiveSurface(const model_t *mod, const int surface_index, con
}
lpoly.surface = surf;
RT_LightAddPolygon(&lpoly);
return lpoly;
}
static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
@ -504,11 +528,25 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
// FIXME move this to rt_light_bsp and static loading
{
qboolean is_emissive = false;
vec3_t emissive;
rt_light_add_polygon_t polylight;
if (psurf && (psurf->flags & Patch_Surface_Emissive)) {
loadEmissiveSurface(mod, surface_index, surf, psurf->emissive);
is_emissive = true;
VectorCopy(psurf->emissive, emissive);
} else if (RT_GetEmissiveForTexture(emissive, tex_id)) {
loadEmissiveSurface(mod, surface_index, surf, emissive);
is_emissive = true;
}
if (is_emissive) {
if (bmodel->polylights) {
ASSERT(bmodel->polylights_count < sizes.emissive_surfaces);
bmodel->polylights[bmodel->polylights_count++] = loadPolyLight(mod, surface_index, surf, emissive);
} else {
polylight = loadPolyLight(mod, surface_index, surf, emissive);
RT_LightAddPolygon(&polylight);
}
}
}
@ -607,6 +645,10 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
XVK_RenderBufferUnlock( index_buffer.buffer );
XVK_RenderBufferUnlock( vertex_buffer.buffer );
if (bmodel->polylights) {
gEngine.Con_Reportf("WHAT %d %d \n", sizes.emissive_surfaces, bmodel->polylights_count);
ASSERT(sizes.emissive_surfaces == bmodel->polylights_count);
}
ASSERT(sizes.num_surfaces == num_geometries);
bmodel->render_model.num_geometries = num_geometries;
@ -640,6 +682,9 @@ 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->polylights = Mem_Malloc(vk_core.pool, sizeof(bmodel->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);
@ -663,6 +708,8 @@ void VK_BrushModelDestroy( model_t *mod ) {
return;
VK_RenderModelDestroy(&bmodel->render_model);
if (bmodel->polylights)
Mem_Free(bmodel->polylights);
Mem_Free(bmodel);
mod->cache.data = NULL;
}

View File

@ -8,18 +8,13 @@ struct draw_list_s;
struct model_s;
struct cl_entity_s;
typedef struct vk_brush_model_s {
vk_render_model_t render_model;
int num_water_surfaces;
} vk_brush_model_t;
qboolean VK_BrushInit( void );
void VK_BrushShutdown( void );
qboolean VK_BrushModelLoad( struct model_s *mod, qboolean map);
void VK_BrushModelDestroy( struct model_s *mod );
void VK_BrushModelDraw( const struct cl_entity_s *ent, int render_mode );
void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, 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 );

View File

@ -1250,6 +1250,7 @@ int RT_LightAddPolygon(const rt_light_add_polygon_t *addpoly) {
{
rt_light_polygon_t *const poly = g_lights.polygons + g_lights.num_polygons;
vec3_t *vertices = g_lights.polygon_vertices + g_lights.num_polygon_vertices;
vec3_t normal;
poly->vertices.offset = g_lights.num_polygon_vertices;
@ -1260,13 +1261,16 @@ int RT_LightAddPolygon(const rt_light_add_polygon_t *addpoly) {
VectorSet(normal, 0, 0, 0);
for (int i = 0; i < addpoly->num_vertices; ++i) {
VectorCopy(addpoly->vertices[i], g_lights.polygon_vertices[poly->vertices.offset + i]);
VectorAdd(addpoly->vertices[i], poly->center, poly->center);
if (addpoly->transform_row)
Matrix3x4_VectorTransform(*addpoly->transform_row, addpoly->vertices[i], vertices[i]);
else
VectorCopy(addpoly->vertices[i], vertices[i]);
VectorAdd(vertices[i], poly->center, poly->center);
if (i > 1) {
vec3_t e[2], lnormal;
VectorSubtract(addpoly->vertices[i-0], addpoly->vertices[0], e[0]);
VectorSubtract(addpoly->vertices[i-1], addpoly->vertices[0], e[1]);
VectorSubtract(vertices[i-0], vertices[0], e[0]);
VectorSubtract(vertices[i-1], vertices[0], e[1]);
CrossProduct(e[0], e[1], lnormal);
VectorAdd(lnormal, normal, normal);
}
@ -1274,28 +1278,32 @@ int RT_LightAddPolygon(const rt_light_add_polygon_t *addpoly) {
poly->area = VectorLength(normal);
VectorM(1.f / poly->area, normal, poly->plane);
poly->plane[3] = -DotProduct(addpoly->vertices[0], poly->plane);
poly->plane[3] = -DotProduct(vertices[0], poly->plane);
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) plane=(%f, %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->plane[0],
poly->plane[1],
poly->plane[2],
poly->plane[3],
poly->area,
poly->vertices.count
);
if (!addpoly->dynamic || debug_dump_lights.enabled) {
gEngine.Con_Reportf("added polygon light index=%d color=(%f, %f, %f) center=(%f, %f, %f) plane=(%f, %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->plane[0],
poly->plane[1],
poly->plane[2],
poly->plane[3],
poly->area,
poly->vertices.count
);
}
{
const vk_light_leaf_set_t *const leafs = getMapLeafsAffectedByMapSurface(addpoly->surface);
const vk_light_leaf_set_t *const leafs = addpoly->dynamic
? getMapLeafsAffectedByMovingSurface( addpoly->surface, addpoly->transform_row )
: getMapLeafsAffectedByMapSurface( addpoly->surface );
addPolygonLeafSetToClusters(leafs, g_lights.num_polygons);
}

View File

@ -122,5 +122,8 @@ typedef struct {
// - bsp/xash/rad/patch-specific stuff
// - mostly engine-agnostic light clusters
const struct msurface_s *surface;
qboolean dynamic;
const matrix3x4 *transform_row;
} rt_light_add_polygon_t;
int RT_LightAddPolygon(const rt_light_add_polygon_t *light);

View File

@ -577,7 +577,7 @@ static void drawEntity( cl_entity_t *ent, int render_mode )
case mod_brush:
R_RotateForEntity( model, ent );
VK_RenderStateSetMatrixModel( model );
VK_BrushModelDraw( ent, render_mode );
VK_BrushModelDraw( ent, render_mode, model );
break;
case mod_studio:
@ -629,7 +629,7 @@ void VK_SceneRender( const ref_viewpass_t *rvp ) {
//VK_LightsBakePVL( 0 /* FIXME frame number */);
VK_RenderStateSetColor( 1.f, 1.f, 1.f, 1.f);
VK_BrushModelDraw( world, kRenderNormal );
VK_BrushModelDraw( world, kRenderNormal, NULL );
}
}