rtx: add studio models

but they crash a lot kek
This commit is contained in:
Ivan 'provod' Avdeev 2021-04-24 12:53:42 -07:00
parent e522acf8b3
commit 9e8ca13dcc
11 changed files with 207 additions and 111 deletions

View File

@ -1,5 +1,11 @@
## 2021-04-24, E86
- [x] rtx: restore studio models
# Next
- [ ] rtx: restore studio models
- [ ] rtx: dynamic models AS caching
- [ ] rtx: better memory handling
- [ ] robust tracking of memory hierarchies: global/static, map, frame
- or just do a generic allocator with compaction?
- [ ] rtx: dynamic surface lights / dynamic light clusters
- [ ] rtx: better light culling: normal, bsp visibility, light volumes and intensity, ...
- [ ] rtx: live rad file reloading (or other solution for tuning lights)
@ -18,6 +24,8 @@
struct LightCluster { uint16 offset, length; }
uint8_t data[];
- [ ] rtx: alpha test/blending
- [ ] make a wrapper for descriptor sets/layouts
- [ ] rtx: coalesce all these buffers
# Planned
- [ ] rtx: denoise
@ -26,7 +34,7 @@
- [ ] SVG+
- [ ] ...
- [ ] rtx: add fps: rasterize into G-buffer, and only then compute lighting with rtx
- [ ] bake light visibility in compute shader
- [ ] rtx: bake light visibility in compute shader
- [ ] rtx: cull light sources (dlights and light textures) using bsp
- [ ] enable entity-parsed lights by lightstyles
- [ ] dlight for flashlight seems to be broken

View File

@ -28,8 +28,8 @@ typedef struct vertex_2d_s {
} vertex_2d_t;
// TODO should these be dynamic?
#define MAX_PICS 8192
#define MAX_BATCHES 128
#define MAX_PICS 16384
#define MAX_BATCHES 256
static struct {
VkPipelineLayout pipeline_layout;

View File

@ -384,19 +384,20 @@ static void R_DrawSegs( vec3_t source, vec3_t delta, float width, float scale, f
VK_RenderBufferUnlock( vertex_buffer );
{
const render_draw_t draw = {
.lightmap = tglob.whiteTexture,
.texture = texture,
.render_mode = render_mode,
.element_count = total_indices,
.vertex_offset = 0,
.index_offset = 0,
.vertex_buffer = vertex_buffer,
.index_buffer = index_buffer,
.emissive = { color[0], color[1], color[2] },
};
// TODO
// const render_draw_t draw = {
// .lightmap = tglob.whiteTexture,
// .texture = texture,
// .render_mode = render_mode,
// .element_count = total_indices,
// .vertex_offset = 0,
// .index_offset = 0,
// .vertex_buffer = vertex_buffer,
// .index_buffer = index_buffer,
// .emissive = { color[0], color[1], color[2] },
// };
VK_RenderScheduleDraw( &draw );
// VK_RenderScheduleDraw( &draw );
}
}

View File

@ -248,6 +248,8 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
model_geometry->texture = t;
model_geometry->vertex_count = surf->numedges;
model_geometry->surface_index = i;
model_geometry->vertex_buffer = vertex_buffer;
model_geometry->index_buffer = index_buffer;
VK_CreateSurfaceLightmap( surf, mod );
@ -311,8 +313,6 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
ASSERT(sizes.num_surfaces == num_surfaces);
bmodel->render_model.num_geometries = num_surfaces;
bmodel->render_model.index_buffer = index_buffer;
bmodel->render_model.vertex_buffer = vertex_buffer;
return true;
}

View File

@ -18,7 +18,9 @@
#define PRINT_NOT_IMPLEMENTED_ARGS(msg, ...) do { \
static int called = 0; \
gEngine.Con_Printf( S_ERROR "VK NOT_IMPLEMENTED(x%d): %s " msg "\n", called, __FUNCTION__, __VA_ARGS__ ); \
if ((called&1023) == 0) { \
gEngine.Con_Printf( S_ERROR "VK NOT_IMPLEMENTED(x%d): %s " msg "\n", called, __FUNCTION__, __VA_ARGS__ ); \
} \
++called; \
} while(0)

View File

@ -399,6 +399,12 @@ void VK_RenderBufferUnlock( vk_buffer_handle_t handle )
// TODO upload from staging to gpumem
}
uint32_t VK_RenderBufferGetOffsetInUnits( vk_buffer_handle_t handle )
{
const vk_buffer_alloc_t *alloc = getBufferFromHandle( handle );
return alloc->buffer_offset_in_units;
}
// Free all LifetimeSingleFrame resources
void VK_RenderBufferClearFrame( void )
{
@ -439,6 +445,15 @@ void VK_RenderBufferPrintStats( void )
#define MAX_DRAW_COMMANDS 8192 // TODO estimate
#define MAX_DEBUG_NAME_LENGTH 32
typedef struct render_draw_s {
int lightmap, texture;
int render_mode;
uint32_t element_count;
uint32_t index_offset, vertex_offset;
vk_buffer_handle_t index_buffer, vertex_buffer;
/* TODO this should be a separate thing? */ struct { float r, g, b; } emissive;
} render_draw_t;
typedef struct {
render_draw_t draw;
uint32_t ubo_offset;
@ -543,7 +558,7 @@ static uint32_t allocUniform( uint32_t size, uint32_t alignment ) {
return offset;
}
void VK_RenderScheduleDraw( const render_draw_t *draw )
static void VK_RenderScheduleDraw( const render_draw_t *draw )
{
const vk_buffer_alloc_t *vertex_buffer = NULL, *index_buffer = NULL;
draw_command_t *draw_command;
@ -831,15 +846,11 @@ void VK_RenderEndRTX( VkCommandBuffer cmdbuf, VkImageView img_dst_view, VkImage
}
}
qboolean VK_RenderModelInit( vk_render_model_t *model) {
qboolean VK_RenderModelInit( vk_render_model_t *model ) {
if (vk_core.rtx) {
// TODO runtime rtx switch: ???
const vk_buffer_alloc_t *vertex_buffer = getBufferFromHandle( model->vertex_buffer );
const vk_buffer_alloc_t *index_buffer = model->index_buffer != InvalidHandle ? getBufferFromHandle( model->index_buffer ) : NULL;
const vk_ray_model_init_t args = {
.buffer = g_render.buffer.buffer,
.index_offset = index_buffer ? index_buffer->buffer_offset_in_units : UINT32_MAX,
.vertex_offset = vertex_buffer->buffer_offset_in_units,
.model = model,
};
model->rtx.blas = VK_NULL_HANDLE;
@ -865,13 +876,15 @@ void VK_RenderModelDraw( vk_render_model_t* model ) {
int current_texture = -1;
int index_count = 0;
int index_offset = -1;
vk_buffer_handle_t vertex_buffer = InvalidHandle;
vk_buffer_handle_t index_buffer = InvalidHandle;
for (int i = 0; i < model->num_geometries; ++i) {
const vk_render_geometry_t *geom = model->geometries + i;
if (geom->texture < 0)
continue;
if (current_texture != geom->texture)
if (current_texture != geom->texture || vertex_buffer != geom->vertex_buffer || index_buffer != geom->index_buffer)
{
if (index_count) {
const render_draw_t draw = {
@ -879,8 +892,8 @@ void VK_RenderModelDraw( vk_render_model_t* model ) {
.texture = current_texture,
.render_mode = model->render_mode,
.element_count = index_count,
.vertex_buffer = model->vertex_buffer,
.index_buffer = model->index_buffer,
.vertex_buffer = vertex_buffer,
.index_buffer = index_buffer,
.vertex_offset = 0,
.index_offset = index_offset,
};
@ -889,6 +902,8 @@ void VK_RenderModelDraw( vk_render_model_t* model ) {
}
current_texture = geom->texture;
vertex_buffer = geom->vertex_buffer;
index_buffer = geom->index_buffer;
index_count = 0;
index_offset = -1;
}
@ -906,8 +921,8 @@ void VK_RenderModelDraw( vk_render_model_t* model ) {
.texture = current_texture,
.render_mode = model->render_mode,
.element_count = index_count,
.vertex_buffer = model->vertex_buffer,
.index_buffer = model->index_buffer,
.vertex_buffer = vertex_buffer,
.index_buffer = index_buffer,
.vertex_offset = 0,
.index_offset = index_offset,
};
@ -915,3 +930,40 @@ void VK_RenderModelDraw( vk_render_model_t* model ) {
VK_RenderScheduleDraw( &draw );
}
}
#define MAX_DYNAMIC_GEOMETRY 256
static struct {
vk_render_model_t model;
vk_render_geometry_t geometries[MAX_DYNAMIC_GEOMETRY];
} g_dynamic_model = {0};
void VK_RenderModelDynamicBegin( const char *debug_name, int render_mode ) {
ASSERT(!g_dynamic_model.model.geometries);
g_dynamic_model.model.debug_name = debug_name;
g_dynamic_model.model.geometries = g_dynamic_model.geometries;
g_dynamic_model.model.num_geometries = 0;
g_dynamic_model.model.render_mode = render_mode;
memset(&g_dynamic_model.model.rtx, 0, sizeof(g_dynamic_model.model.rtx));
}
void VK_RenderModelDynamicAddGeometry( const vk_render_geometry_t *geom ) {
ASSERT(g_dynamic_model.model.geometries);
if (g_dynamic_model.model.num_geometries == MAX_DYNAMIC_GEOMETRY) {
gEngine.Con_Printf(S_ERROR "Ran out of dynamic model geometry slots for model %s\n", g_dynamic_model.model.debug_name);
return;
}
g_dynamic_model.geometries[g_dynamic_model.model.num_geometries++] = *geom;
}
void VK_RenderModelDynamicCommit( void ) {
ASSERT(g_dynamic_model.model.geometries);
if (g_dynamic_model.model.num_geometries > 0) {
g_dynamic_model.model.dynamic = true;
VK_RenderModelInit( &g_dynamic_model.model );
VK_RenderModelDraw( &g_dynamic_model );
}
g_dynamic_model.model.debug_name = NULL;
g_dynamic_model.model.geometries = NULL;
}

View File

@ -25,6 +25,7 @@ typedef enum {
vk_buffer_handle_t VK_RenderBufferAlloc( uint32_t unit_size, uint32_t count, vk_lifetime_t lifetime );
vk_buffer_lock_t VK_RenderBufferLock( vk_buffer_handle_t handle );
void VK_RenderBufferUnlock( vk_buffer_handle_t handle );
uint32_t VK_RenderBufferGetOffsetInUnits( vk_buffer_handle_t handle );
// TODO buffer refcount when doing RTX AS updates? need to store buffer handles somewhere between frames
@ -60,22 +61,20 @@ typedef struct vk_vertex_s {
vec2_t lm_tc; //float p3_[2];
} vk_vertex_t;
typedef struct render_draw_s {
int lightmap, texture;
int render_mode;
uint32_t element_count;
uint32_t index_offset, vertex_offset;
vk_buffer_handle_t index_buffer, vertex_buffer;
/* TODO this should be a separate thing? */ struct { float r, g, b; } emissive;
} render_draw_t;
typedef struct {
int texture;
uint32_t element_count;
vk_buffer_handle_t index_buffer, vertex_buffer;
uint32_t index_offset, vertex_offset;
// TODO can be dynamic
int texture;
uint32_t element_count;
uint32_t vertex_count;
// TODO we don't really need this here
// as it's used to tie emissive surfaces to geometry in RTX renderer
// we can and should infer this dynamically (from texture) when building dynamic light clusters
int surface_index;
// TODO potentially dynamic int light_cluster;
} vk_render_geometry_t;
typedef struct vk_render_model_s {
@ -84,11 +83,10 @@ typedef struct vk_render_model_s {
int num_geometries;
vk_render_geometry_t *geometries;
// Common for the entire model
vk_buffer_handle_t index_buffer, vertex_buffer;
// TODO potentially dynamic data: textures
//qboolean dynamic; // whether this model will require data reupload
// This model will be one-frame only, its buffers are not preserved between frames
qboolean dynamic;
struct {
VkAccelerationStructureKHR blas;
@ -102,12 +100,12 @@ void VK_RenderModelDraw( vk_render_model_t* model );
void VK_RenderFrameBegin( void );
// void VK_RenderObjectBegin( void *tag, const char *name /* expect transient ... */ );
// void VK_RenderObjectEnd();
void VK_RenderModelDynamicBegin( const char *debug_name, int render_mode );
void VK_RenderModelDynamicAddGeometry( const vk_render_geometry_t *geom );
void VK_RenderModelDynamicCommit( void );
void VK_RenderScheduleDraw( const render_draw_t *draw );
void VK_RenderFrameEnd( VkCommandBuffer cmdbuf );
void VK_RenderFrameEndRTX( VkCommandBuffer cmdbuf, VkImageView img_dst_view, VkImage img_dst, uint32_t w, uint32_t h );
void VK_RenderDebugLabelBegin( const char *label );
void VK_RenderDebugLabelEnd( void );
// void VK_RenderDebugLabelBegin( const char *label );
// void VK_RenderDebugLabelEnd( void );

View File

@ -62,6 +62,7 @@ typedef struct {
matrix3x4 transform_row;
VkAccelerationStructureKHR accel;
uint32_t kusochki_offset;
qboolean dynamic;
} vk_ray_model_t;
typedef struct {
@ -108,6 +109,10 @@ static struct {
int num_lighttextures;
vk_ray_model_t models[MAX_ACCELS];
uint32_t scratch_offset; // for building dynamic blases
// for dynamic models
uint32_t buffer_offset_at_frame_begin;
int num_kusochki_at_frame_begin;
} frame;
unsigned frame_number;
@ -243,9 +248,30 @@ void VK_RayFrameBegin( void )
{
ASSERT(vk_core.rtx);
// 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
// destroy/reuse dynamic ASes from previous frame
for (int i = 0; i < g_rtx.frame.num_models; ++i) {
vk_ray_model_t *model = g_rtx.frame.models + i;
if (!model->dynamic)
continue;
// TODO cache and reuse
for (int j = 0; j < ARRAYSIZE(g_rtx.blases); ++j) {
if (g_rtx.blases[j] == model->accel) {
vkDestroyAccelerationStructureKHR(vk_core.device, g_rtx.blases[j], NULL);
g_rtx.blases[j] = VK_NULL_HANDLE;
model->accel = VK_NULL_HANDLE;
}
}
}
g_rtx.frame.scratch_offset = 0;
g_rtx.frame.num_models = 0;
g_rtx.frame.num_lighttextures = 0;
g_rtx.frame.buffer_offset_at_frame_begin = g_rtx.map.buffer_offset;
g_rtx.frame.num_kusochki_at_frame_begin = g_rtx.map.num_kusochki;
}
void VK_RayFrameAddModelDynamic( VkCommandBuffer cmdbuf, const vk_ray_model_dynamic_t *dynamic)
@ -703,6 +729,10 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args)
args->dst.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region,
VK_FILTER_NEAREST);
}
// Restore dynamic buffer offset
g_rtx.map.buffer_offset = g_rtx.frame.buffer_offset_at_frame_begin;
g_rtx.map.num_kusochki = g_rtx.frame.num_kusochki_at_frame_begin;
}
static void createLayouts( void ) {
@ -965,8 +995,8 @@ qboolean VK_RayModelInit( vk_ray_model_init_t args ) {
ASSERT(vk_core.rtx);
ASSERT(g_rtx.map.num_kusochki <= MAX_KUSOCHKI);
if (g_rtx.map.num_kusochki == MAX_KUSOCHKI) {
gEngine.Con_Printf(S_ERROR "Maximum number of kusochki exceeded\n");
if (g_rtx.map.num_kusochki + args.model->num_geometries > MAX_KUSOCHKI) {
gEngine.Con_Printf(S_ERROR "Maximum number of kusochki exceeded on model %s\n", args.model->debug_name);
return false;
}
@ -981,8 +1011,8 @@ qboolean VK_RayModelInit( vk_ray_model_init_t args ) {
for (int i = 0; i < args.model->num_geometries; ++i) {
const vk_render_geometry_t *mg = args.model->geometries + i;
const uint32_t prim_count = mg->element_count / 3;
const uint32_t vertex_offset = args.vertex_offset + mg->vertex_offset;
const uint32_t index_offset = args.index_offset + mg->index_offset;
const uint32_t vertex_offset = mg->vertex_offset + VK_RenderBufferGetOffsetInUnits(mg->vertex_buffer);
const uint32_t index_offset = mg->index_buffer == InvalidHandle ? UINT32_MAX : (mg->index_offset + VK_RenderBufferGetOffsetInUnits(mg->index_buffer));
const qboolean is_emissive = ((mg->texture >= 0 && mg->texture < MAX_TEXTURES)
? g_emissive_texture_table[mg->texture].set
: false);
@ -996,7 +1026,7 @@ qboolean VK_RayModelInit( vk_ray_model_init_t args ) {
.geometry.triangles =
(VkAccelerationStructureGeometryTrianglesDataKHR){
.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR,
.indexType = args.index_offset == UINT32_MAX ? VK_INDEX_TYPE_NONE_KHR : VK_INDEX_TYPE_UINT16,
.indexType = mg->index_buffer == InvalidHandle ? VK_INDEX_TYPE_NONE_KHR : VK_INDEX_TYPE_UINT16,
.maxVertex = mg->vertex_count,
.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT,
.vertexStride = sizeof(vk_vertex_t),
@ -1122,6 +1152,7 @@ void VK_RayFrameAddModel( const struct vk_render_model_s *model, const matrix3x4
ASSERT(model->rtx.blas != VK_NULL_HANDLE);
ray_model->accel = model->rtx.blas;
ray_model->kusochki_offset = model->rtx.kusochki_offset;
ray_model->dynamic = model->dynamic;
memcpy(ray_model->transform_row, *transform_row, sizeof(ray_model->transform_row));
g_rtx.frame.num_models++;
}

View File

@ -7,7 +7,6 @@ struct vk_render_model_s;
typedef struct {
struct vk_render_model_s *model;
VkBuffer buffer;
uint32_t vertex_offset, index_offset;
} vk_ray_model_init_t;
qboolean VK_RayModelInit( vk_ray_model_init_t model_init);

View File

@ -706,18 +706,19 @@ static void R_DrawSpriteQuad( mspriteframe_t *frame, vec3_t org, vec3_t v_right,
VK_RenderBufferUnlock( vertex_buffer );
{
const render_draw_t draw = {
.lightmap = tglob.whiteTexture,
.texture = texture,
.render_mode = render_mode,
.element_count = 6,
.vertex_offset = 0,
.index_offset = 0,
.vertex_buffer = vertex_buffer,
.index_buffer = index_buffer,
};
// TODO
// const render_draw_t draw = {
// .lightmap = tglob.whiteTexture,
// .texture = texture,
// .render_mode = render_mode,
// .element_count = 6,
// .vertex_offset = 0,
// .index_offset = 0,
// .vertex_buffer = vertex_buffer,
// .index_buffer = index_buffer,
// };
VK_RenderScheduleDraw( &draw );
// VK_RenderScheduleDraw( &draw );
}
}
@ -940,7 +941,7 @@ void VK_SpriteDrawModel( cl_entity_t *e )
if( oldframe == frame )
{
// draw the single non-lerped frame
/* FIXME VK make sure we end up with the same values
ubo->color[0] = color[0];
ubo->color[1] = color[1];

View File

@ -600,16 +600,16 @@ float R_StudioEstimateFrame( cl_entity_t *e, mstudioseqdesc_t *pseqdesc )
if( pseqdesc->numframes <= 1 ) f = 0.0;
else f = (e->curstate.frame * (pseqdesc->numframes - 1)) / 256.0f;
f += dfdt;
if( pseqdesc->flags & STUDIO_LOOPING )
if( pseqdesc->flags & STUDIO_LOOPING )
{
if( pseqdesc->numframes > 1 )
f -= (int)(f / (pseqdesc->numframes - 1)) * (pseqdesc->numframes - 1);
if( f < 0 ) f += (pseqdesc->numframes - 1);
}
else
else
{
if( f >= pseqdesc->numframes - 1.001 )
f = pseqdesc->numframes - 1.001;
@ -719,7 +719,7 @@ StudioCalcBoneAdj
void R_StudioCalcBoneAdj( float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2, byte mouthopen )
{
mstudiobonecontroller_t *pbonecontroller;
float value = 0.0f;
float value = 0.0f;
int i, j;
pbonecontroller = (mstudiobonecontroller_t *)((byte *)m_pStudioHeader + m_pStudioHeader->bonecontrollerindex);
@ -732,7 +732,7 @@ void R_StudioCalcBoneAdj( float dadt, float *adj, const byte *pcontroller1, cons
{
// mouth hardcoded at controller 4
value = (float)mouthopen / 64.0f;
value = bound( 0.0f, value, 1.0f );
value = bound( 0.0f, value, 1.0f );
value = (1.0f - value) * pbonecontroller[j].start + value * pbonecontroller[j].end;
}
else if( i < 4 )
@ -746,12 +746,12 @@ void R_StudioCalcBoneAdj( float dadt, float *adj, const byte *pcontroller1, cons
int b = (pcontroller2[i] + 128) % 256;
value = (( a * dadt ) + ( b * ( 1.0f - dadt )) - 128) * (360.0f / 256.0f) + pbonecontroller[j].start;
}
else
else
{
value = ((pcontroller1[i] * dadt + (pcontroller2[i]) * (1.0f - dadt))) * (360.0f / 256.0f) + pbonecontroller[j].start;
}
}
else
else
{
value = (pcontroller1[i] * dadt + pcontroller2[i] * (1.0f - dadt)) / 255.0f;
value = bound( 0.0f, value, 1.0f );
@ -811,7 +811,7 @@ void R_StudioCalcRotations( cl_entity_t *e, float pos[][3], vec4_t *q, mstudiose
R_StudioCalcBoneAdj( dadt, adj, e->curstate.controller, e->latched.prevcontroller, e->mouth.mouthopen );
for( i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++ )
for( i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++ )
{
gEngine.R_StudioCalcBoneQuaternion( frame, s, pbone, panim, adj, q[i] );
gEngine.R_StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] );
@ -850,7 +850,7 @@ void R_StudioMergeBones( cl_entity_t *e, model_t *m_pSubModel )
R_StudioCalcRotations( e, pos, q, pseqdesc, panim, f );
pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex);
for( i = 0; i < m_pStudioHeader->numbones; i++ )
for( i = 0; i < m_pStudioHeader->numbones; i++ )
{
for( j = 0; j < g_studio.cached_numbones; j++ )
{
@ -865,15 +865,15 @@ void R_StudioMergeBones( cl_entity_t *e, model_t *m_pSubModel )
if( j >= g_studio.cached_numbones )
{
Matrix3x4_FromOriginQuat( bonematrix, q[i], pos[i] );
if( pbones[i].parent == -1 )
if( pbones[i].parent == -1 )
{
Matrix3x4_ConcatTransforms( g_studio.bonestransform[i], g_studio.rotationmatrix, bonematrix );
Matrix3x4_Copy( g_studio.lighttransform[i], g_studio.bonestransform[i] );
// apply client-side effects to the transformation matrix
R_StudioFxTransform( e, g_studio.bonestransform[i] );
}
else
}
else
{
Matrix3x4_ConcatTransforms( g_studio.bonestransform[i], g_studio.bonestransform[pbones[i].parent], bonematrix );
Matrix3x4_ConcatTransforms( g_studio.lighttransform[i], g_studio.lighttransform[pbones[i].parent], bonematrix );
@ -997,7 +997,7 @@ void R_StudioSetupBones( cl_entity_t *e )
{
qboolean copy_bones = true;
if( m_pPlayerInfo->gaitsequence >= m_pStudioHeader->numseq )
if( m_pPlayerInfo->gaitsequence >= m_pStudioHeader->numseq )
m_pPlayerInfo->gaitsequence = 0;
pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pPlayerInfo->gaitsequence;
@ -1019,18 +1019,18 @@ void R_StudioSetupBones( cl_entity_t *e )
}
}
for( i = 0; i < m_pStudioHeader->numbones; i++ )
for( i = 0; i < m_pStudioHeader->numbones; i++ )
{
Matrix3x4_FromOriginQuat( bonematrix, q[i], pos[i] );
if( pbones[i].parent == -1 )
if( pbones[i].parent == -1 )
{
Matrix3x4_ConcatTransforms( g_studio.bonestransform[i], g_studio.rotationmatrix, bonematrix );
Matrix3x4_Copy( g_studio.lighttransform[i], g_studio.bonestransform[i] );
// apply client-side effects to the transformation matrix
R_StudioFxTransform( e, g_studio.bonestransform[i] );
}
}
else
{
Matrix3x4_ConcatTransforms( g_studio.bonestransform[i], g_studio.bonestransform[pbones[i].parent], bonematrix );
@ -1053,7 +1053,7 @@ static void R_StudioSaveBones( void )
pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex);
g_studio.cached_numbones = m_pStudioHeader->numbones;
for( i = 0; i < m_pStudioHeader->numbones; i++ )
for( i = 0; i < m_pStudioHeader->numbones; i++ )
{
Matrix3x4_Copy( g_studio.cached_bonestransform[i], g_studio.bonestransform[i] );
Matrix3x4_Copy( g_studio.cached_lighttransform[i], g_studio.lighttransform[i] );
@ -1131,7 +1131,7 @@ void R_StudioGenerateNormals( void )
for( i = 0; i < m_pSubModel->numverts; i++ )
VectorClear( g_studio.norms[i] );
for( j = 0; j < m_pSubModel->nummesh; j++ )
for( j = 0; j < m_pSubModel->nummesh; j++ )
{
short *ptricmds;
@ -1626,8 +1626,8 @@ void R_StudioLighting( float *lv, int bone, int flags, vec3_t normal )
if( FBitSet( flags, STUDIO_NF_FLATSHADE ))
{
illum += g_studio.shadelight * 0.8f;
}
else
}
else
{
float r, lightcos;
@ -1646,14 +1646,14 @@ void R_StudioLighting( float *lv, int bone, int flags, vec3_t normal )
{
r += 1.0f;
lightcos = (( r - 1.0f ) - lightcos) / r;
if( lightcos > 0.0f )
illum += g_studio.shadelight * lightcos;
if( lightcos > 0.0f )
illum += g_studio.shadelight * lightcos;
}
else
{
lightcos = (lightcos + ( r - 1.0f )) / r;
if( lightcos > 0.0f )
illum -= g_studio.shadelight * lightcos;
illum -= g_studio.shadelight * lightcos;
}
illum = Q_max( illum, 0.0f );
@ -1906,7 +1906,7 @@ static int R_StudioMeshCompare( const void *a, const void *b )
return 0;
}
static void R_StudioDrawNormalMesh( short *ptricmds, vec3_t *pstudionorms, float s, float t, int render_mode, int texture )
static void R_StudioDrawNormalMesh( short *ptricmds, vec3_t *pstudionorms, float s, float t, int texture )
{
float *lv;
int i;
@ -1928,7 +1928,7 @@ static void R_StudioDrawNormalMesh( short *ptricmds, vec3_t *pstudionorms, float
num_indices += (vertices-2) * 3;
ptricmds += 4 * vertices;
}
ASSERT(num_vertices > 0);
ASSERT(num_indices > 0);
@ -2009,18 +2009,22 @@ static void R_StudioDrawNormalMesh( short *ptricmds, vec3_t *pstudionorms, float
// Render
{
const render_draw_t draw = {
.lightmap = tglob.whiteTexture,
const vk_render_geometry_t geometry = {
//.lightmap = tglob.whiteTexture,
.surface_index = -1,
.texture = texture,
.render_mode = render_mode,
.element_count = num_indices,
.vertex_offset = 0,
.index_offset = 0,
.vertex_count = num_vertices,
.vertex_buffer = vertex_buffer,
.vertex_offset = 0,
.element_count = num_indices,
.index_offset = 0,
.index_buffer = index_buffer,
};
VK_RenderScheduleDraw( &draw );
VK_RenderModelDynamicAddGeometry( &geometry );
}
}
@ -2113,7 +2117,7 @@ static void R_StudioDrawPoints( void )
if( !m_pStudioHeader ) return;
VK_RenderDebugLabelBegin( m_pSubModel->name );
VK_RenderModelDynamicBegin( m_pSubModel->name, RI.currententity->curstate.rendermode );
g_studio.numverts = g_studio.numelems = 0;
@ -2168,7 +2172,7 @@ static void R_StudioDrawPoints( void )
R_StudioGenerateNormals();
for( j = k = 0; j < m_pSubModel->nummesh; j++ )
for( j = k = 0; j < m_pSubModel->nummesh; j++ )
{
g_nFaceFlags = ptexture[pskinref[pmesh[j].skinref]].flags | g_nForceFaceFlags;
@ -2261,7 +2265,7 @@ static void R_StudioDrawPoints( void )
R_StudioDrawChromeMesh( ptricmds, pstudionorms, s, t, shellscale );
else if( FBitSet( g_nFaceFlags, STUDIO_NF_UV_COORDS ))
R_StudioDrawFloatMesh( ptricmds, pstudionorms );
else*/ R_StudioDrawNormalMesh( ptricmds, pstudionorms, s, t, RI.currententity->curstate.rendermode, texture );
else*/ R_StudioDrawNormalMesh( ptricmds, pstudionorms, s, t, texture );
/* FIXME VK
if( FBitSet( g_nFaceFlags, STUDIO_NF_MASKED ))
@ -2281,7 +2285,7 @@ static void R_StudioDrawPoints( void )
*/
}
VK_RenderDebugLabelEnd();
VK_RenderModelDynamicCommit();
}
static void R_StudioSetRemapColors( int newTop, int newBottom )
@ -2644,7 +2648,7 @@ void GL_StudioSetRenderMode( int rendermode )
}
*/
}
/*
===============
GL_StudioDrawShadow
@ -2787,7 +2791,7 @@ void R_StudioProcessGait( entity_state_t *pplayer )
int iBlend;
float dt, flYaw; // view direction relative to movement
if( RI.currententity->curstate.sequence >= m_pStudioHeader->numseq )
if( RI.currententity->curstate.sequence >= m_pStudioHeader->numseq )
RI.currententity->curstate.sequence = 0;
dt = bound( 0.0f, g_studio.frametime, 1.0f );
@ -2835,7 +2839,7 @@ void R_StudioProcessGait( entity_state_t *pplayer )
if( RI.currententity->angles[YAW] < -0 ) RI.currententity->angles[YAW] += 360.0f;
RI.currententity->latched.prevangles[YAW] = RI.currententity->angles[YAW];
if( pplayer->gaitsequence >= m_pStudioHeader->numseq )
if( pplayer->gaitsequence >= m_pStudioHeader->numseq )
pplayer->gaitsequence = 0;
pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + pplayer->gaitsequence;
@ -2873,7 +2877,7 @@ static int R_StudioDrawPlayer( int flags, entity_state_t *pplayer )
m_pPlayerInfo = pfnPlayerInfo( m_nPlayerIndex );
VectorCopy( RI.currententity->angles, orig_angles );
R_StudioProcessGait( pplayer );
m_pPlayerInfo->gaitsequence = pplayer->gaitsequence;
@ -2892,7 +2896,7 @@ static int R_StudioDrawPlayer( int flags, entity_state_t *pplayer )
RI.currententity->latched.prevcontroller[1] = RI.currententity->curstate.controller[1];
RI.currententity->latched.prevcontroller[2] = RI.currententity->curstate.controller[2];
RI.currententity->latched.prevcontroller[3] = RI.currententity->curstate.controller[3];
m_pPlayerInfo = pfnPlayerInfo( m_nPlayerIndex );
m_pPlayerInfo->gaitsequence = 0;
@ -3259,7 +3263,7 @@ static void R_StudioLoadTexture( model_t *mod, studiohdr_t *phdr, mstudiotexture
int flags = 0;
char texname[128], name[128], mdlname[128];
texture_t *tx = NULL;
if( ptexture->flags & STUDIO_NF_NORMALMAP )
flags |= (TF_NORMALMAP);