mirror of
https://github.com/w23/xash3d-fwgs
synced 2024-12-15 21:50:59 +01:00
rt denoiser: motion vectors for raytracing pipeline and for ray query
This commit is contained in:
commit
c4881f57c9
@ -17,6 +17,9 @@ layout(set = 0, binding = 4, rgba16f) uniform readonly image2D light_point_diffu
|
||||
layout(set = 0, binding = 5, rgba16f) uniform readonly image2D light_point_specular;
|
||||
layout(set = 0, binding = 6, rgba16f) uniform readonly image2D emissive;
|
||||
|
||||
layout(set = 0, binding = 7, rgba32f) uniform readonly image2D position_t;
|
||||
layout(set = 0, binding = 8, rgba32f) uniform readonly image2D prev_position_t;
|
||||
|
||||
//layout(set = 0, binding = 7, rgba32f) uniform readonly image2D position_t;
|
||||
//layout(set = 0, binding = 8, rgba16f) uniform readonly image2D normals_gs;
|
||||
|
||||
@ -204,6 +207,9 @@ void main() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// DEBUG motion vectors
|
||||
//colour = vec3(length(imageLoad(position_t, pix).rgb - imageLoad(prev_position_t, pix).rgb));
|
||||
|
||||
imageStore(out_dest, pix, vec4(colour, 0.));
|
||||
//imageStore(out_dest, pix, imageLoad(light_poly, pix));
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
struct RayPayloadOpaque {
|
||||
float t_offset, pixel_cone_spread_angle;
|
||||
vec4 hit_pos_t;
|
||||
vec4 prev_pos_t;
|
||||
vec3 normal;
|
||||
vec3 geometry_normal;
|
||||
vec3 base_color;
|
||||
|
@ -18,6 +18,7 @@
|
||||
X(12, normals_gs, rgba16f) \
|
||||
X(13, material_rmxx, rgba8) \
|
||||
X(14, emissive, rgba16f) \
|
||||
X(15, prev_position_t, rgba32f) \
|
||||
|
||||
#define RAY_LIGHT_DIRECT_INPUTS(X) \
|
||||
X(10, position_t, rgba32f) \
|
||||
@ -104,6 +105,8 @@ struct Kusok {
|
||||
float roughness;
|
||||
float metalness;
|
||||
PAD(2)
|
||||
|
||||
mat4 prev_transform;
|
||||
};
|
||||
|
||||
struct PointLight {
|
||||
@ -154,6 +157,7 @@ struct PushConstants {
|
||||
|
||||
struct UniformBuffer {
|
||||
mat4 inv_proj, inv_view;
|
||||
mat4 prev_inv_proj, prev_inv_view;
|
||||
float ray_cone_width;
|
||||
uint random_seed;
|
||||
PAD(2)
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
struct Vertex {
|
||||
vec3 pos;
|
||||
vec3 prev_pos;
|
||||
vec3 normal;
|
||||
vec3 tangent;
|
||||
vec2 gl_tc;
|
||||
|
@ -55,4 +55,5 @@ void main() {
|
||||
imageStore(out_normals_gs, pix, payload.normals_gs);
|
||||
imageStore(out_material_rmxx, pix, payload.material_rmxx);
|
||||
imageStore(out_emissive, pix, payload.emissive);
|
||||
imageStore(out_prev_position_t, pix, payload.prev_pos_t);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ void main() {
|
||||
Geometry geom = readHitGeometry(bary, ubo.ubo.ray_cone_width);
|
||||
|
||||
payload.hit_t = vec4(geom.pos, gl_HitTEXT);
|
||||
payload.prev_pos_t = vec4(geom.prev_pos, 0.);
|
||||
|
||||
const Kusok kusok = getKusok(geom.kusok_index);
|
||||
const uint tex_base_color = kusok.tex_base_color;
|
||||
|
@ -41,4 +41,5 @@ void main() {
|
||||
imageStore(out_normals_gs, ivec2(gl_LaunchIDEXT.xy), payload.normals_gs);
|
||||
imageStore(out_material_rmxx, ivec2(gl_LaunchIDEXT.xy), payload.material_rmxx);
|
||||
imageStore(out_emissive, ivec2(gl_LaunchIDEXT.xy), payload.emissive);
|
||||
imageStore(out_prev_position_t, ivec2(gl_LaunchIDEXT.xy), payload.prev_pos_t);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
struct RayPayloadPrimary {
|
||||
vec4 hit_t;
|
||||
vec4 prev_pos_t;
|
||||
vec4 base_color_a;
|
||||
vec4 normals_gs;
|
||||
vec4 material_rmxx;
|
||||
|
@ -21,6 +21,7 @@ void primaryRayHit(rayQueryEXT rq, inout RayPayloadPrimary payload) {
|
||||
const float hitT = rayQueryGetIntersectionTEXT(rq, true); //gl_HitTEXT;
|
||||
const vec3 rayDirection = rayQueryGetWorldRayDirectionEXT(rq); //gl_WorldRayDirectionEXT
|
||||
payload.hit_t = vec4(geom.pos, hitT);
|
||||
payload.prev_pos_t = vec4(geom.prev_pos, 0.);
|
||||
|
||||
const Kusok kusok = getKusok(geom.kusok_index);
|
||||
const uint tex_base_color = kusok.tex_base_color;
|
||||
|
@ -42,6 +42,7 @@ vec4 computeAnisotropicEllipseAxes(in vec3 P, in vec3 f,
|
||||
|
||||
struct Geometry {
|
||||
vec3 pos;
|
||||
vec3 prev_pos;
|
||||
|
||||
vec2 uv;
|
||||
vec4 uv_lods;
|
||||
@ -87,6 +88,12 @@ Geometry readHitGeometry(vec2 bary, float ray_cone_width) {
|
||||
objectToWorld * vec4(getVertex(vi3).pos, 1.f),
|
||||
};
|
||||
|
||||
const vec3 prev_pos[3] = {
|
||||
(kusok.prev_transform * vec4(getVertex(vi1).prev_pos, 1.f)).xyz,
|
||||
(kusok.prev_transform * vec4(getVertex(vi2).prev_pos, 1.f)).xyz,
|
||||
(kusok.prev_transform * vec4(getVertex(vi3).prev_pos, 1.f)).xyz,
|
||||
};
|
||||
|
||||
const vec2 uvs[3] = {
|
||||
getVertex(vi1).gl_tc,
|
||||
getVertex(vi2).gl_tc,
|
||||
@ -94,6 +101,7 @@ Geometry readHitGeometry(vec2 bary, float ray_cone_width) {
|
||||
};
|
||||
|
||||
geom.pos = baryMix(pos[0], pos[1], pos[2], bary);
|
||||
geom.prev_pos = baryMix(prev_pos[0], prev_pos[1], prev_pos[2], bary);
|
||||
geom.uv = baryMix(uvs[0], uvs[1], uvs[2], bary);
|
||||
//TODO or not TODO? const vec2 texture_uv = texture_uv_stationary + push_constants.time * kusok.uv_speed;
|
||||
|
||||
|
@ -33,6 +33,16 @@ static struct {
|
||||
int rtable[MOD_FRAMES][MOD_FRAMES];
|
||||
} g_brush;
|
||||
|
||||
|
||||
#define MAX_BRUSH_ENTITIES_PREV_STATES 1024
|
||||
|
||||
typedef struct {
|
||||
matrix4x4 prev_model_transform;
|
||||
float prev_time;
|
||||
} brush_entity_prev_state_t;
|
||||
|
||||
static brush_entity_prev_state_t g_brush_prev_states[MAX_BRUSH_ENTITIES_PREV_STATES];
|
||||
|
||||
void VK_InitRandomTable( void )
|
||||
{
|
||||
int tu, tv;
|
||||
@ -82,6 +92,7 @@ static void EmitWaterPolys( const cl_entity_t *ent, const msurface_t *warp, qboo
|
||||
{
|
||||
const float time = gpGlobals->time;
|
||||
float *v, nv, waveHeight;
|
||||
float prev_nv, prev_time;
|
||||
float s, t, os, ot;
|
||||
glpoly_t *p;
|
||||
int i;
|
||||
@ -90,6 +101,11 @@ static void EmitWaterPolys( const cl_entity_t *ent, const msurface_t *warp, qboo
|
||||
uint16_t *indices;
|
||||
r_geometry_buffer_lock_t buffer;
|
||||
|
||||
if (ent->index < MAX_BRUSH_ENTITIES_PREV_STATES) {
|
||||
prev_time = g_brush_prev_states[ent->index].prev_time;
|
||||
g_brush_prev_states[ent->index].prev_time = time;
|
||||
} else gEngine.Con_Printf(S_ERROR "Brush entities previous frame states pool is overflow, increase it. Index is %s\n", ent->index );
|
||||
|
||||
#define MAX_WATER_VERTICES 16
|
||||
vk_vertex_t poly_vertices[MAX_WATER_VERTICES];
|
||||
|
||||
@ -135,6 +151,10 @@ static void EmitWaterPolys( const cl_entity_t *ent, const msurface_t *warp, qboo
|
||||
nv = r_turbsin[(int)(time * 160.0f + v[1] + v[0]) & 255] + 8.0f;
|
||||
nv = (r_turbsin[(int)(v[0] * 5.0f + time * 171.0f - v[1]) & 255] + 8.0f ) * 0.8f + nv;
|
||||
nv = nv * waveHeight + v[2];
|
||||
|
||||
prev_nv = r_turbsin[(int)(prev_time * 160.0f + v[1] + v[0]) & 255] + 8.0f;
|
||||
prev_nv = (r_turbsin[(int)(v[0] * 5.0f + prev_time * 171.0f - v[1]) & 255] + 8.0f ) * 0.8f + prev_nv;
|
||||
prev_nv = prev_nv * waveHeight + v[2];
|
||||
}
|
||||
else nv = v[2];
|
||||
|
||||
@ -151,6 +171,10 @@ static void EmitWaterPolys( const cl_entity_t *ent, const msurface_t *warp, qboo
|
||||
poly_vertices[i].pos[1] = v[1];
|
||||
poly_vertices[i].pos[2] = nv;
|
||||
|
||||
poly_vertices[i].prev_pos[0] = v[0];
|
||||
poly_vertices[i].prev_pos[1] = v[1];
|
||||
poly_vertices[i].prev_pos[2] = prev_nv;
|
||||
|
||||
poly_vertices[i].gl_tc[0] = s;
|
||||
poly_vertices[i].gl_tc[1] = t;
|
||||
|
||||
@ -265,9 +289,17 @@ void XVK_DrawWaterSurfaces( const cl_entity_t *ent )
|
||||
EmitWaterPolys( ent, surf, false );
|
||||
}
|
||||
|
||||
int entity_id = ent->index;
|
||||
|
||||
if (entity_id < MAX_BRUSH_ENTITIES_PREV_STATES)
|
||||
Matrix4x4_Copy( *VK_RenderGetLastFrameTransform(), g_brush_prev_states[entity_id].prev_model_transform );
|
||||
|
||||
// submit as dynamic model
|
||||
VK_RenderModelDynamicCommit();
|
||||
|
||||
if (entity_id < MAX_BRUSH_ENTITIES_PREV_STATES)
|
||||
Matrix4x4_Copy( g_brush_prev_states[entity_id].prev_model_transform, *VK_RenderGetLastFrameTransform() );
|
||||
|
||||
// TODO:
|
||||
// - upload water geometry only once, animate in compute/vertex shader
|
||||
}
|
||||
@ -360,8 +392,18 @@ void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, const matrix4x4
|
||||
}
|
||||
}
|
||||
|
||||
int entity_id = ent->index;
|
||||
if (entity_id < MAX_BRUSH_ENTITIES_PREV_STATES) {
|
||||
Matrix4x4_Copy( bmodel->render_model.prev_transform,
|
||||
g_brush_prev_states[entity_id].prev_model_transform );
|
||||
} else gEngine.Con_Printf(S_ERROR "Brush entities previous frame states pool is overflow, increase it. Index is %s\n", ent->index );
|
||||
|
||||
bmodel->render_model.render_mode = render_mode;
|
||||
VK_RenderModelDraw(ent, &bmodel->render_model);
|
||||
|
||||
if (entity_id >= 0 && entity_id < MAX_BRUSH_ENTITIES_PREV_STATES) {
|
||||
Matrix4x4_Copy( g_brush_prev_states[entity_id].prev_model_transform, bmodel->render_model.prev_transform );
|
||||
}
|
||||
}
|
||||
|
||||
static qboolean renderableSurface( const msurface_t *surf, int i ) {
|
||||
@ -576,6 +618,10 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
|
||||
{in_vertex->position[0], in_vertex->position[1], in_vertex->position[2]},
|
||||
};
|
||||
|
||||
vertex.prev_pos[0] = in_vertex->position[0];
|
||||
vertex.prev_pos[1] = in_vertex->position[1];
|
||||
vertex.prev_pos[2] = in_vertex->position[2];
|
||||
|
||||
float s = DotProduct( in_vertex->position, surf->texinfo->vecs[0] ) + surf->texinfo->vecs[0][3];
|
||||
float t = DotProduct( in_vertex->position, surf->texinfo->vecs[1] ) + surf->texinfo->vecs[1][3];
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
typedef struct vk_vertex_s {
|
||||
// TODO padding needed for storage buffer reading, figure out how to fix in GLSL/SPV side
|
||||
vec3_t pos; float p0_;
|
||||
vec3_t prev_pos; float p01_;
|
||||
vec3_t normal; uint32_t flags;
|
||||
vec3_t tangent; uint32_t p1_;
|
||||
vec2_t gl_tc; //float p2_[2];
|
||||
|
@ -301,6 +301,7 @@ vk_ray_model_t* VK_RayModelCreate( vk_ray_model_init_t args ) {
|
||||
|
||||
const vec3_t color = {1, 1, 1};
|
||||
applyMaterialToKusok(kusochki + i, mg, color, false);
|
||||
Matrix4x4_LoadIdentity(kusochki[i].prev_transform);
|
||||
}
|
||||
|
||||
R_VkStagingUnlock(kusok_staging.handle);
|
||||
@ -493,6 +494,8 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render
|
||||
for (int i = 0; i < render_model->num_geometries; ++i) {
|
||||
const vk_render_geometry_t *geom = render_model->geometries + i;
|
||||
applyMaterialToKusok(kusochki + i, geom, color, HACK_reflective);
|
||||
|
||||
Matrix4x4_Copy((kusochki + i)->prev_transform, render_model->prev_transform);
|
||||
}
|
||||
|
||||
/* gEngine.Con_Reportf("model %s: geom=%d kuoffs=%d kustoff=%d kustsz=%d sthndl=%d\n", */
|
||||
|
@ -87,6 +87,7 @@ static qboolean createPipelines( void )
|
||||
{.binding = 0, .location = 3, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(vk_vertex_t, lm_tc)},
|
||||
{.binding = 0, .location = 4, .format = VK_FORMAT_R8G8B8A8_UNORM, .offset = offsetof(vk_vertex_t, color)},
|
||||
{.binding = 0, .location = 5, .format = VK_FORMAT_R32_UINT, .offset = offsetof(vk_vertex_t, flags)},
|
||||
{.binding = 0, .location = 6, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk_vertex_t, prev_pos)},
|
||||
};
|
||||
|
||||
const vk_shader_stage_t shader_stages[] = {
|
||||
@ -682,6 +683,9 @@ void VK_RenderModelDraw( const cl_entity_t *ent, vk_render_model_t* model ) {
|
||||
|
||||
if (g_render_state.current_frame_is_ray_traced) {
|
||||
VK_RayFrameAddModel(model->ray_model, model, (const matrix3x4*)g_render_state.model, g_render_state.dirty_uniform_data.color, ent ? ent->curstate.rendercolor : (color24){255,255,255});
|
||||
|
||||
// store current transform here before it puts to entity history
|
||||
Matrix4x4_Copy( model->prev_transform, g_render_state.model );
|
||||
return;
|
||||
}
|
||||
|
||||
@ -747,6 +751,10 @@ static struct {
|
||||
vk_render_geometry_t geometries[MAX_DYNAMIC_GEOMETRY];
|
||||
} g_dynamic_model = {0};
|
||||
|
||||
matrix4x4 *VK_RenderGetLastFrameTransform() {
|
||||
return &g_dynamic_model.model.prev_transform;
|
||||
}
|
||||
|
||||
void VK_RenderModelDynamicBegin( int render_mode, const char *debug_name_fmt, ... ) {
|
||||
va_list argptr;
|
||||
va_start( argptr, debug_name_fmt );
|
||||
|
@ -82,6 +82,9 @@ typedef struct vk_render_model_s {
|
||||
struct vk_ray_model_s *ray_model;
|
||||
struct rt_light_add_polygon_s *polylights;
|
||||
int polylights_count;
|
||||
|
||||
// previous frame ObjectToWorld (model) matrix
|
||||
matrix4x4 prev_transform;
|
||||
} vk_render_model_t;
|
||||
|
||||
qboolean VK_RenderModelInit( vk_render_model_t* model );
|
||||
@ -100,3 +103,5 @@ void VK_RenderEnd( VkCommandBuffer cmdbuf );
|
||||
void VK_RenderEndRTX( VkCommandBuffer cmdbuf, VkImageView img_dst_view, VkImage img_dst, uint32_t w, uint32_t h );
|
||||
|
||||
void VK_Render_FIXME_Barrier( VkCommandBuffer cmdbuf );
|
||||
|
||||
matrix4x4* VK_RenderGetLastFrameTransform();
|
||||
|
@ -156,6 +156,13 @@ static void prepareUniformBuffer( const vk_ray_frame_render_args_t *args, int fr
|
||||
Matrix4x4_Invert_Full(view_inv, *args->view);
|
||||
Matrix4x4_ToArrayFloatGL(view_inv, (float*)ubo->inv_view);
|
||||
|
||||
// last frame matrices
|
||||
static matrix4x4 prev_inv_proj, prev_inv_view;
|
||||
Matrix4x4_ToArrayFloatGL(prev_inv_proj, (float*)ubo->prev_inv_proj);
|
||||
Matrix4x4_ToArrayFloatGL(prev_inv_view, (float*)ubo->prev_inv_view);
|
||||
Matrix4x4_Copy(prev_inv_view, view_inv);
|
||||
Matrix4x4_Copy(prev_inv_proj, proj_inv);
|
||||
|
||||
ubo->ray_cone_width = atanf((2.0f*tanf(DEG2RAD(fov_angle_y) * 0.5f)) / (float)FRAME_HEIGHT);
|
||||
ubo->random_seed = (uint32_t)gEngine.COM_RandomLong(0, INT32_MAX);
|
||||
}
|
||||
|
@ -47,6 +47,11 @@ typedef struct sortedmesh_s
|
||||
int flags; // face flags
|
||||
} sortedmesh_t;
|
||||
|
||||
typedef struct {
|
||||
matrix3x4 worldtransform[MAXSTUDIOBONES];
|
||||
matrix4x4 prev_transform;
|
||||
} studio_entity_prev_state_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double time;
|
||||
@ -74,6 +79,8 @@ typedef struct
|
||||
vec3_t verts[MAXSTUDIOVERTS];
|
||||
vec3_t norms[MAXSTUDIOVERTS];
|
||||
|
||||
vec3_t prev_verts[MAXSTUDIOVERTS]; // last frame state for motion vectors
|
||||
|
||||
// lighting state
|
||||
float ambientlight;
|
||||
float shadelight;
|
||||
@ -118,6 +125,9 @@ static cvar_t *cl_himodels;
|
||||
static r_studio_interface_t *pStudioDraw;
|
||||
static studio_draw_state_t g_studio; // global studio state
|
||||
|
||||
#define MAX_ENTITIES_PREV_STATES_STUDIO 1024
|
||||
static studio_entity_prev_state_t g_entity_prev_states[MAX_ENTITIES_PREV_STATES_STUDIO];
|
||||
|
||||
// global variables
|
||||
static qboolean m_fDoRemap;
|
||||
mstudiomodel_t *m_pSubModel;
|
||||
@ -254,7 +264,7 @@ static qboolean R_StudioComputeBBox( vec3_t bbox[8] )
|
||||
return true; // visible
|
||||
}
|
||||
|
||||
void R_StudioComputeSkinMatrix( mstudioboneweight_t *boneweights, matrix3x4 result )
|
||||
void R_StudioComputeSkinMatrix( mstudioboneweight_t *boneweights, matrix3x4 *worldtransform, matrix3x4 result )
|
||||
{
|
||||
float flWeight0, flWeight1, flWeight2, flWeight3;
|
||||
int i, numbones = 0;
|
||||
@ -268,10 +278,10 @@ void R_StudioComputeSkinMatrix( mstudioboneweight_t *boneweights, matrix3x4 resu
|
||||
|
||||
if( numbones == 4 )
|
||||
{
|
||||
vec4_t *boneMat0 = (vec4_t *)g_studio.worldtransform[boneweights->bone[0]];
|
||||
vec4_t *boneMat1 = (vec4_t *)g_studio.worldtransform[boneweights->bone[1]];
|
||||
vec4_t *boneMat2 = (vec4_t *)g_studio.worldtransform[boneweights->bone[2]];
|
||||
vec4_t *boneMat3 = (vec4_t *)g_studio.worldtransform[boneweights->bone[3]];
|
||||
vec4_t *boneMat0 = (vec4_t *)worldtransform[boneweights->bone[0]];
|
||||
vec4_t *boneMat1 = (vec4_t *)worldtransform[boneweights->bone[1]];
|
||||
vec4_t *boneMat2 = (vec4_t *)worldtransform[boneweights->bone[2]];
|
||||
vec4_t *boneMat3 = (vec4_t *)worldtransform[boneweights->bone[3]];
|
||||
flWeight0 = boneweights->weight[0] / 255.0f;
|
||||
flWeight1 = boneweights->weight[1] / 255.0f;
|
||||
flWeight2 = boneweights->weight[2] / 255.0f;
|
||||
@ -295,9 +305,9 @@ void R_StudioComputeSkinMatrix( mstudioboneweight_t *boneweights, matrix3x4 resu
|
||||
}
|
||||
else if( numbones == 3 )
|
||||
{
|
||||
vec4_t *boneMat0 = (vec4_t *)g_studio.worldtransform[boneweights->bone[0]];
|
||||
vec4_t *boneMat1 = (vec4_t *)g_studio.worldtransform[boneweights->bone[1]];
|
||||
vec4_t *boneMat2 = (vec4_t *)g_studio.worldtransform[boneweights->bone[2]];
|
||||
vec4_t *boneMat0 = (vec4_t *)worldtransform[boneweights->bone[0]];
|
||||
vec4_t *boneMat1 = (vec4_t *)worldtransform[boneweights->bone[1]];
|
||||
vec4_t *boneMat2 = (vec4_t *)worldtransform[boneweights->bone[2]];
|
||||
flWeight0 = boneweights->weight[0] / 255.0f;
|
||||
flWeight1 = boneweights->weight[1] / 255.0f;
|
||||
flWeight2 = boneweights->weight[2] / 255.0f;
|
||||
@ -320,8 +330,8 @@ void R_StudioComputeSkinMatrix( mstudioboneweight_t *boneweights, matrix3x4 resu
|
||||
}
|
||||
else if( numbones == 2 )
|
||||
{
|
||||
vec4_t *boneMat0 = (vec4_t *)g_studio.worldtransform[boneweights->bone[0]];
|
||||
vec4_t *boneMat1 = (vec4_t *)g_studio.worldtransform[boneweights->bone[1]];
|
||||
vec4_t *boneMat0 = (vec4_t *)worldtransform[boneweights->bone[0]];
|
||||
vec4_t *boneMat1 = (vec4_t *)worldtransform[boneweights->bone[1]];
|
||||
flWeight0 = boneweights->weight[0] / 255.0f;
|
||||
flWeight1 = boneweights->weight[1] / 255.0f;
|
||||
flTotal = flWeight0 + flWeight1;
|
||||
@ -343,7 +353,7 @@ void R_StudioComputeSkinMatrix( mstudioboneweight_t *boneweights, matrix3x4 resu
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix3x4_Copy( result, g_studio.worldtransform[boneweights->bone[0]] );
|
||||
Matrix3x4_Copy( result, worldtransform[boneweights->bone[0]] );
|
||||
}
|
||||
}
|
||||
|
||||
@ -1062,6 +1072,26 @@ static void R_StudioSaveBones( void )
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
SaveTransformsForNextFrame
|
||||
|
||||
====================
|
||||
*/
|
||||
|
||||
static void R_StudioSaveTransformsForNextFrame( matrix3x4* bones_transforms )
|
||||
{
|
||||
if (RI.currententity->index >= MAX_ENTITIES_PREV_STATES_STUDIO)
|
||||
return;
|
||||
|
||||
studio_entity_prev_state_t *prev_state = &g_entity_prev_states[RI.currententity->index];
|
||||
|
||||
for( int i = 0; i < m_pStudioHeader->numbones; i++ )
|
||||
{
|
||||
Matrix3x4_Copy(prev_state->worldtransform[i], bones_transforms[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
StudioBuildNormalTable
|
||||
@ -1946,6 +1976,7 @@ static void R_StudioDrawNormalMesh( short *ptricmds, vec3_t *pstudionorms, float
|
||||
*dst_vtx = (vk_vertex_t){0};
|
||||
|
||||
VectorCopy(g_studio.verts[ptricmds[0]], dst_vtx->pos);
|
||||
VectorCopy(g_studio.prev_verts[ptricmds[0]], dst_vtx->prev_pos);
|
||||
VectorCopy(g_studio.norms[ptricmds[0]], dst_vtx->normal);
|
||||
dst_vtx->lm_tc[0] = dst_vtx->lm_tc[1] = 0.f;
|
||||
|
||||
@ -2127,6 +2158,14 @@ static void R_StudioDrawPoints( void )
|
||||
pskinref = (short *)((byte *)m_pStudioHeader + m_pStudioHeader->skinindex);
|
||||
if( m_skinnum != 0 ) pskinref += (m_skinnum * m_pStudioHeader->numskinref);
|
||||
|
||||
studio_entity_prev_state_t *prev_frame_state = &g_entity_prev_states[RI.currententity->index];
|
||||
|
||||
if (RI.currententity->index >= MAX_ENTITIES_PREV_STATES_STUDIO)
|
||||
{
|
||||
gEngine.Con_Printf(S_ERROR "Studio entities previous frame states pool is overflow, increase it. Index is %s\n", RI.currententity->index);
|
||||
prev_frame_state = &g_entity_prev_states[MAX_ENTITIES_PREV_STATES_STUDIO - 1]; // fallback to last element
|
||||
}
|
||||
|
||||
if( FBitSet( m_pStudioHeader->flags, STUDIO_HAS_BONEWEIGHTS ) && m_pSubModel->blendvertinfoindex != 0 && m_pSubModel->blendnorminfoindex != 0 )
|
||||
{
|
||||
mstudioboneweight_t *pvertweight = (mstudioboneweight_t *)((byte *)m_pStudioHeader + m_pSubModel->blendvertinfoindex);
|
||||
@ -2135,24 +2174,35 @@ static void R_StudioDrawPoints( void )
|
||||
|
||||
for( i = 0; i < m_pSubModel->numverts; i++ )
|
||||
{
|
||||
R_StudioComputeSkinMatrix( &pvertweight[i], skinMat );
|
||||
R_StudioComputeSkinMatrix( &pvertweight[i], g_studio.worldtransform, skinMat );
|
||||
Matrix3x4_VectorTransform( skinMat, pstudioverts[i], g_studio.verts[i] );
|
||||
R_LightStrength( pvertbone[i], pstudioverts[i], g_studio.lightpos[i] );
|
||||
}
|
||||
|
||||
for( i = 0; i < m_pSubModel->numverts; i++ )
|
||||
{
|
||||
R_StudioComputeSkinMatrix( &pvertweight[i], prev_frame_state->worldtransform, skinMat );
|
||||
Matrix3x4_VectorTransform( skinMat, pstudioverts[i], g_studio.prev_verts[i] );
|
||||
}
|
||||
|
||||
for( i = 0; i < m_pSubModel->numnorms; i++ )
|
||||
{
|
||||
R_StudioComputeSkinMatrix( &pnormweight[i], skinMat );
|
||||
R_StudioComputeSkinMatrix( &pnormweight[i], g_studio.worldtransform, skinMat );
|
||||
Matrix3x4_VectorRotate( skinMat, pstudionorms[i], g_studio.norms[i] );
|
||||
}
|
||||
|
||||
R_StudioSaveTransformsForNextFrame (g_studio.worldtransform );
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < m_pSubModel->numverts; i++ )
|
||||
{
|
||||
Matrix3x4_VectorTransform( g_studio.bonestransform[pvertbone[i]], pstudioverts[i], g_studio.verts[i] );
|
||||
Matrix3x4_VectorTransform( prev_frame_state->worldtransform[pvertbone[i]], pstudioverts[i], g_studio.prev_verts[i] );
|
||||
R_LightStrength( pvertbone[i], pstudioverts[i], g_studio.lightpos[i] );
|
||||
}
|
||||
|
||||
R_StudioSaveTransformsForNextFrame( g_studio.bonestransform );
|
||||
}
|
||||
|
||||
// generate shared normals for properly scaling glowing shell
|
||||
@ -2278,7 +2328,17 @@ static void R_StudioDrawPoints( void )
|
||||
*/
|
||||
}
|
||||
|
||||
int entity_id = RI.currententity->index;
|
||||
|
||||
if (entity_id < MAX_ENTITIES_PREV_STATES_STUDIO) {
|
||||
Matrix4x4_Copy( *VK_RenderGetLastFrameTransform(), g_entity_prev_states[entity_id].prev_transform );
|
||||
} else gEngine.Con_Printf(S_ERROR "Studio entities last states pool is overflow, increase it. Index is %s\n", entity_id );
|
||||
|
||||
VK_RenderModelDynamicCommit();
|
||||
|
||||
if (entity_id < MAX_ENTITIES_PREV_STATES_STUDIO) {
|
||||
Matrix4x4_Copy( g_entity_prev_states[entity_id].prev_transform, *VK_RenderGetLastFrameTransform() );
|
||||
}
|
||||
}
|
||||
|
||||
static void R_StudioSetRemapColors( int newTop, int newBottom )
|
||||
|
Loading…
Reference in New Issue
Block a user