rtx: enable patching surface textures

example:
```
{
	"_xvk_surface_id" "489"
	"_xvk_texture" "#maps/test_material.bsp:debug_normal1.mip"
}
```

if _xvk_texture is empty, then the surface will be deleted

surfaces can be deleted or their
This commit is contained in:
Ivan Avdeev 2021-11-26 23:59:48 -08:00
parent ecaac9d4c7
commit 28d047a904
6 changed files with 145 additions and 29 deletions

View File

@ -11,6 +11,7 @@
#include "vk_scene.h"
#include "vk_render.h"
#include "vk_light.h"
#include "vk_mapents.h"
#include "ref_params.h"
#include "eiface.h"
@ -279,9 +280,9 @@ R_TextureAnimation
Returns the proper texture for a given time and surface
===============
*/
texture_t *R_TextureAnimation( const cl_entity_t *ent, const msurface_t *s )
static const texture_t *R_TextureAnimation( const cl_entity_t *ent, const msurface_t *s, const struct texture_s *base_override )
{
texture_t *base = s->texinfo->texture;
const texture_t *base = base_override ? base_override : s->texinfo->texture;
int count, reletive;
if( ent && ent->curstate.frame )
@ -344,11 +345,14 @@ void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode )
return;
for (int i = 0; i < bmodel->render_model.num_geometries; ++i) {
texture_t *t = R_TextureAnimation(ent, bmodel->render_model.geometries[i].surf);
vk_render_geometry_t *geom = bmodel->render_model.geometries + i;
const int surface_index = geom->surf - mod->surfaces;
const struct texture_s *override = g_map_entities.patch.surfaces ? g_map_entities.patch.surfaces[surface_index].tex : NULL;
const texture_t *t = R_TextureAnimation(ent, geom->surf, override);
if (t->gl_texturenum < 0)
continue;
bmodel->render_model.geometries[i].texture = t->gl_texturenum;
geom->texture = t->gl_texturenum;
}
bmodel->render_model.render_mode = render_mode;
@ -373,6 +377,9 @@ static qboolean renderableSurface( const msurface_t *surf, int i ) {
// PRINTFLAGS(PRINTFLAG)
// gEngine.Con_Reportf("\n");
// }
//
if (g_map_entities.patch.surfaces && g_map_entities.patch.surfaces[i].tex_id == Patch_Surface_Delete)
return false;
//if( surf->flags & ( SURF_DRAWSKY | SURF_DRAWTURB | SURF_CONVEYOR | SURF_DRAWTURB_QUADS ) ) {
if( surf->flags & ( SURF_DRAWTURB | SURF_DRAWTURB_QUADS ) ) {
@ -457,11 +464,18 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
const float sample_size = gEngine.Mod_SampleSizeForFace( surf );
int index_count = 0;
vec3_t tangent;
int tex_id = surf->texinfo->texture->gl_texturenum;
if (!renderableSurface(surf, -1))
continue;
if (t != surf->texinfo->texture->gl_texturenum)
if (g_map_entities.patch.surfaces) {
const int patch = g_map_entities.patch.surfaces[surface_index].tex_id;
if (patch != Patch_Surface_NoPatch)
tex_id = patch;
}
if (t != tex_id)
continue;
++num_geometries;
@ -476,7 +490,7 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
}
model_geometry->surf = surf;
model_geometry->texture = surf->texinfo->texture->gl_texturenum;
model_geometry->texture = tex_id;
model_geometry->vertex_offset = vertex_buffer.buffer.unit.offset;
model_geometry->max_vertex = vertex_offset + surf->numedges;

View File

@ -337,7 +337,7 @@ static void clusterBitMapClear( void ) {
// Returns true if wasn't set
static qboolean clusterBitMapCheckOrSet( int cell_index ) {
uint32_t *const bits = g_lights_tmp.clusters_bit_map + (cell_index / 32);
const uint32_t bit = 1 << (cell_index % 32);
const uint32_t bit = 1u << (cell_index % 32);
if ((*bits) & bit)
return false;
@ -875,6 +875,10 @@ static void processStaticPointLights( void ) {
case LightTypeEnvironment:
index = addSpotLight(le, default_radius, le->style, hack_attenuation_spot, i == g_map_entities.single_environment_index);
break;
default:
ASSERT(!"Unexpected light type");
continue;
}
if (index < 0)
@ -902,7 +906,6 @@ void VK_LightsLoadMapStaticLights( void ) {
}
}
XVK_ParseMapEntities();
processStaticPointLights();
// Load RAD data based on map name

View File

@ -1,5 +1,7 @@
#include "vk_common.h"
#include "vk_mapents.h"
#include "vk_core.h" // TODO we need only pool from there, not the entire vulkan garbage
#include "vk_textures.h"
#include "eiface.h" // ARRAYSIZE
#include "xash3d_mathlib.h"
@ -245,33 +247,52 @@ static void addTargetEntity( const entity_props_t *props ) {
++g_map_entities.num_targets;
}
const xvk_mapent_target_t *findTargetByName(const char *name) {
for (int i = 0; i < g_map_entities.num_targets; ++i) {
const xvk_mapent_target_t *target = g_map_entities.targets + i;
if (Q_strcmp(name, target->targetname) == 0)
return target;
}
return NULL;
}
static void readWorldspawn( const entity_props_t *props ) {
Q_strcpy(g_map_entities.wadlist, props->wad);
}
void XVK_ParseMapEntities( void ) {
static void addPatchSurface( const entity_props_t *props ) {
const model_t* const map = gEngine.pfnGetModelByIndex( 1 );
char *pos;
const int num_surfaces = map->numsurfaces;
if (props->_xvk_surface_id < 0 || props->_xvk_surface_id >= num_surfaces) {
gEngine.Con_Printf(S_ERROR "Incorrect patch for surface_index %d where numsurfaces=%d\n", props->_xvk_surface_id, num_surfaces);
return;
}
if (!g_map_entities.patch.surfaces) {
g_map_entities.patch.surfaces = Mem_Malloc(vk_core.pool, num_surfaces * sizeof(xvk_patch_surface_t));
for (int i = 0; i < num_surfaces; ++i) {
g_map_entities.patch.surfaces[i].tex_id = Patch_Surface_NoPatch;
g_map_entities.patch.surfaces[i].tex = NULL;
}
}
if (props->_xvk_texture[0] != '\0') {
const int tex_id = VK_FindTexture( props->_xvk_texture );
gEngine.Con_Printf(S_WARN "Patch for surface %d with texture \"%s\" -> %d\n", props->_xvk_surface_id, props->_xvk_texture, tex_id);
g_map_entities.patch.surfaces[props->_xvk_surface_id].tex_id = tex_id;
// Find texture_t for this index
for (int i = 0; i < map->numtextures; ++i) {
const texture_t* const tex = map->textures[i];
if (tex->gl_texturenum == tex_id) {
g_map_entities.patch.surfaces[props->_xvk_surface_id].tex = tex;
break;
}
}
return;
}
gEngine.Con_Reportf("Patch: surface %d removed\n", props->_xvk_surface_id);
g_map_entities.patch.surfaces[props->_xvk_surface_id].tex_id = Patch_Surface_Delete;
g_map_entities.patch.surfaces[props->_xvk_surface_id].tex = NULL;
}
static void parseEntities( char *string ) {
unsigned have_fields = 0;
entity_props_t values;
ASSERT(map);
g_map_entities.num_targets = 0;
g_map_entities.num_lights = 0;
g_map_entities.single_environment_index = NoEnvironmentLights;
pos = map->entities;
char *pos = string;
//gEngine.Con_Reportf("ENTITIES: %s\n", pos);
for (;;) {
char key[1024];
@ -302,6 +323,10 @@ void XVK_ParseMapEntities( void ) {
break;
case Unknown:
if (have_fields & Field__xvk_surface_id && have_fields & Field__xvk_texture) {
addPatchSurface( &values );
}
break;
case Ignored:
// Skip
break;
@ -327,7 +352,19 @@ void XVK_ParseMapEntities( void ) {
}
#undef CHECK_FIELD
}
}
const xvk_mapent_target_t *findTargetByName(const char *name) {
for (int i = 0; i < g_map_entities.num_targets; ++i) {
const xvk_mapent_target_t *target = g_map_entities.targets + i;
if (Q_strcmp(name, target->targetname) == 0)
return target;
}
return NULL;
}
static void orientSpotlights( void ) {
// Patch spotlight directions based on target entities
for (int i = 0; i < g_map_entities.num_lights; ++i) {
vk_light_entity_t *const light = g_map_entities.lights + i;
@ -352,3 +389,39 @@ void XVK_ParseMapEntities( void ) {
light->dir[0], light->dir[1], light->dir[2]);
}
}
static void parsePatches( const model_t *const map ) {
char filename[256];
byte *data;
if (g_map_entities.patch.surfaces) {
Mem_Free(g_map_entities.patch.surfaces);
g_map_entities.patch.surfaces = NULL;
}
Q_snprintf(filename, sizeof(filename), "luchiki/%s.patch", map->name);
gEngine.Con_Reportf("Loading patches from file \"%s\"\n", filename);
data = gEngine.COM_LoadFile( filename, 0, false );
if (!data) {
gEngine.Con_Reportf("No patch file \"%s\"\n", filename);
return;
}
parseEntities( (char*)data );
Mem_Free(data);
}
void XVK_ParseMapEntities( void ) {
const model_t* const map = gEngine.pfnGetModelByIndex( 1 );
ASSERT(map);
g_map_entities.num_targets = 0;
g_map_entities.num_lights = 0;
g_map_entities.single_environment_index = NoEnvironmentLights;
parseEntities( map->entities );
parsePatches( map );
orientSpotlights();
}

View File

@ -15,6 +15,10 @@
X(10, string, targetname, String) \
X(11, string, target, String) \
X(12, int, style, Int) \
X(13, int, _xvk_surface_id, Int) \
X(14, string, _xvk_texture, String) \
//X(13, int, _xvk_ent_id, Int) \
typedef enum {
Unknown = 0,
@ -58,6 +62,22 @@ typedef struct {
vec3_t origin;
} xvk_mapent_target_t;
enum {
Patch_Surface_NoPatch = -1,
Patch_Surface_Delete = -2,
};
struct texture_s;
typedef struct {
int tex_id;
const struct texture_s *tex;
} xvk_patch_surface_t;
typedef struct {
xvk_patch_surface_t *surfaces;
} xvk_patch_t;
#define MAX_MAPENT_TARGETS 256
typedef struct {
@ -70,6 +90,8 @@ typedef struct {
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;

View File

@ -125,7 +125,7 @@ static void loadMaterialsFromFile( const char *filename ) {
Q_snprintf(texture_path, sizeof(texture_path), "pbr%s", value);
} else {
// Path relative to current material.mat file
Q_snprintf(texture_path, sizeof(texture_path), "%.*s%s", path_end - path_begin, path_begin, value);
Q_snprintf(texture_path, sizeof(texture_path), "%.*s%s", (int)(path_end - path_begin), path_begin, value);
}
tex_id = loadTexture(texture_path, force_reload);

View File

@ -15,6 +15,7 @@
#include "vk_cvar.h"
#include "vk_materials.h"
#include "camera.h"
#include "vk_mapents.h"
#include "com_strings.h"
#include "ref_params.h"
@ -132,6 +133,9 @@ void R_NewMap( void )
XVK_CHECK(vkBeginCommandBuffer(vk_core.cb, &beginfo));
}
// Load light entities and patch data prior to loading map brush model
XVK_ParseMapEntities();
// Load all models at once
gEngine.Con_Reportf( "Num models: %d:\n", num_models );
for( int i = 0; i < num_models; i++ )