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:
parent
ecaac9d4c7
commit
28d047a904
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++ )
|
||||
|
|
Loading…
Reference in New Issue