diff --git a/include/QF/GLSL/qf_bsp.h b/include/QF/GLSL/qf_bsp.h index c9648962c..d4faec802 100644 --- a/include/QF/GLSL/qf_bsp.h +++ b/include/QF/GLSL/qf_bsp.h @@ -60,7 +60,7 @@ typedef struct elechain_s { struct elechain_s *next; int model_index; elements_t *elements; - vec4f_t *transform; + const vec4f_t *transform; float *color; } elechain_t; diff --git a/include/QF/model.h b/include/QF/model.h index 0acfc7246..2e01dd1f9 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -79,7 +79,7 @@ typedef struct instsurf_s { struct instsurf_s *tex_chain; ///< next in texture chain struct instsurf_s *lm_chain; ///< next in lightmap chain struct msurface_s *surface; ///< surface to render - vec4f_t *transform; + const vec4f_t *transform; float *color; } instsurf_t; diff --git a/include/QF/scene/entity.h b/include/QF/scene/entity.h index 19b0a40cf..7ad097e85 100644 --- a/include/QF/scene/entity.h +++ b/include/QF/scene/entity.h @@ -80,7 +80,6 @@ typedef struct renderer_s { int fullbright; float min_light; int render_id; - mat4f_t full_transform; } renderer_t; typedef struct entityset_s DARRAY_TYPE (entity_t) entityset_t; diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index fa4ca02cc..f14e42258 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -60,6 +60,8 @@ #include "r_internal.h" #include "vid_gl.h" +static struct DARRAY_TYPE (mat4f_t) ent_transforms = DARRAY_STATIC_INIT (16); + static instsurf_t *waterchain = NULL; static instsurf_t **waterchain_tail = &waterchain; static instsurf_t *sky_chain; @@ -509,7 +511,7 @@ gl_R_DrawBrushModel (entity_t e) glbspctx_t bspctx = { brush, Ent_GetComponent (e.id, scene_animation, e.reg), - renderer->full_transform, + ent_transforms.a[ent_transforms.size++], renderer->colormod, }; @@ -564,7 +566,7 @@ gl_R_DrawBrushModel (entity_t e) qfglPushMatrix (); gl_R_RotateForEntity (Transform_GetWorldMatrixPtr (transform)); - qfglGetFloatv (GL_MODELVIEW_MATRIX, (vec_t*)&renderer->full_transform[0]); + qfglGetFloatv (GL_MODELVIEW_MATRIX, (vec_t*)&bspctx.transform[0]); qfglPopMatrix (); surf = &brush->surfaces[brush->firstmodelsurface]; @@ -720,8 +722,12 @@ gl_R_DrawWorld (void) gl_R_DrawSkyChain (sky_chain); if (r_drawentities) { - for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { \ - entity_t ent = r_ent_queue->ent_queues[mod_brush].a[i]; \ + size_t count = r_ent_queue->ent_queues[mod_brush].size; + // ensure pointer stability of the matrix array during this frame + DARRAY_RESIZE (&ent_transforms, count); + ent_transforms.size = 0; + for (size_t i = 0; i < count; i++) { + entity_t ent = r_ent_queue->ent_queues[mod_brush].a[i]; gl_R_DrawBrushModel (ent); } } diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 79f0ff9fd..66aa7ac86 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -239,7 +239,7 @@ static struct { typedef struct glslbspctx_s { mod_brush_t *brush; animation_t *animation; - vec4f_t *transform; + const vec4f_t *transform; float *color; } glslbspctx_t; @@ -662,14 +662,11 @@ R_DrawBrushModel (entity_t e) glslbspctx_t bctx = { brush, Ent_GetComponent (e.id, scene_animation, e.reg), - renderer->full_transform, + Transform_GetWorldMatrixPtr (Entity_Transform (e)), renderer->colormod, }; - mat4f_t mat; - transform_t transform = Entity_Transform (e); - Transform_GetWorldMatrix (transform, mat); - memcpy (renderer->full_transform, mat, sizeof (mat));//FIXME + auto mat = bctx.transform; if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { rotated = true; radius = model->radius; diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index ad8211ed5..305f3ddd4 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -67,6 +67,24 @@ typedef struct { uint32_t matrix_base; } shadow_push_constants_t; +static renderer_t * +alias_get_renderer (entity_t ent) +{ + return Ent_GetComponent (ent.id, scene_renderer, ent.reg); +} + +static animation_t * +alias_get_animation (entity_t ent) +{ + return Ent_GetComponent (ent.id, scene_animation, ent.reg); +} + +static colormap_t * +alias_get_colormap (entity_t ent) +{ + return Ent_GetComponent (ent.id, scene_colormap, ent.reg); +} + static void alias_depth_range (qfv_taskctx_t *taskctx, float minDepth, float maxDepth) { @@ -160,9 +178,9 @@ push_shadow_constants (const mat4f_t mat, float blend, uint16_t *matrix_base, } static void -alias_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass) +alias_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass, + renderer_t *renderer) { - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); auto model = renderer->model; aliashdr_t *hdr; qfv_alias_skin_t *skin; @@ -172,8 +190,7 @@ alias_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass) hdr = Cache_Get (&model->cache); } - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - ent.reg); + auto animation = alias_get_animation (ent); float blend = R_AliasGetLerpedFrames (animation, hdr); transform_t transform = Entity_Transform (ent); @@ -190,7 +207,7 @@ alias_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass) QuatCopy (renderer->colormod, base_color); QuatCopy (skin->colors, colors); if (Ent_HasComponent (ent.id, scene_colormap, ent.reg)) { - colormap_t *colormap=Ent_GetComponent (ent.id, scene_colormap, ent.reg); + auto colormap = alias_get_colormap (ent); colors[0] = colormap->top * 16 + 8; colors[1] = colormap->bottom * 16 + 8; } @@ -264,12 +281,13 @@ alias_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto queue = r_ent_queue; //FIXME fetch from scene for (size_t i = 0; i < queue->ent_queues[mod_alias].size; i++) { entity_t ent = queue->ent_queues[mod_alias].a[i]; + auto renderer = alias_get_renderer (ent); // FIXME hack the depth range to prevent view model // from poking into walls if (vmod && ent.id == vr_data.view_model.id) { alias_depth_range (taskctx, 0.7, 1); } - alias_draw_ent (taskctx, ent, pass); + alias_draw_ent (taskctx, ent, pass, renderer); // unhack in case the view_model is not the last if (vmod && ent.id == vr_data.view_model.id) { alias_depth_range (taskctx, 0, 1);