[renderer] Split entity queue into per-model-type

While I doubt the difference is all that significant, this should speed
up entity rendering because it cuts out a lot of branching, and
eliminates scanning the same list multiple times only to not do anything
for large chunks of the list.
This commit is contained in:
Bill Currie 2022-03-02 15:00:32 +09:00
parent ab91d73635
commit ae6970a005
13 changed files with 334 additions and 315 deletions

View file

@ -373,7 +373,14 @@ typedef struct {
// Whole model ================================================================
typedef enum {mod_brush, mod_sprite, mod_alias, mod_iqm} modtype_t;
typedef enum {
mod_brush,
mod_sprite,
mod_alias,
mod_iqm,
mod_num_types
} modtype_t;
#define EF_ROCKET 1 // leave a trail
#define EF_GRENADE 2 // leave a trail

View file

@ -292,7 +292,7 @@ extern mleaf_t *r_viewleaf;
extern int r_clipflags;
extern int r_dlightframecount;
extern struct entity_s *r_ent_queue;
extern struct entity_s *r_ent_queue[mod_num_types];
struct dlight_s;
extern vec3_t lightspot;

View file

@ -598,11 +598,8 @@ gl_overbright_f (cvar_t *var)
if (!gl_R_BuildLightMap)
return;
for (ent = r_ent_queue; ent; ent = ent->next) {
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) {
m = ent->renderer.model;
if (m->type != mod_brush)
continue;
if (m->path[0] == '*')
continue;

View file

@ -220,9 +220,7 @@ R_DrawEntitiesOnList (void)
qfglEnable (GL_NORMALIZE);
}
for (ent = r_ent_queue; ent; ent = ent->next) {
if (ent->renderer.model->type != mod_alias)
continue;
for (ent = r_ent_queue[mod_alias]; ent; ent = ent->next) {
gl_R_DrawAliasModel (ent);
}
qfglColor3ubv (color_white);
@ -250,9 +248,7 @@ R_DrawEntitiesOnList (void)
qglActiveTexture (gl_mtex_enum + 0);
}
for (ent = r_ent_queue; ent; ent = ent->next) {
if (ent->renderer.model->type != mod_iqm)
continue;
for (ent = r_ent_queue[mod_iqm]; ent; ent = ent->next) {
gl_R_DrawIQMModel (ent);
}
qfglColor3ubv (color_white);
@ -261,9 +257,7 @@ R_DrawEntitiesOnList (void)
qfglEnable (GL_ALPHA_TEST);
if (gl_va_capable)
qfglInterleavedArrays (GL_T2F_C4UB_V3F, 0, gl_spriteVertexArray);
for (ent = r_ent_queue; ent; ent = ent->next) {
if (ent->renderer.model->type != mod_sprite)
continue;
for (ent = r_ent_queue[mod_sprite]; ent; ent = ent->next) {
R_DrawSpriteModel (ent);
}
qfglDisable (GL_ALPHA_TEST);

View file

@ -741,10 +741,7 @@ gl_R_DrawWorld (void)
R_VisitWorldNodes (&bctx);
if (r_drawentities->int_val) {
entity_t *ent;
for (ent = r_ent_queue; ent; ent = ent->next) {
if (ent->renderer.model->type != mod_brush) {
continue;
}
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) {
gl_R_DrawBrushModel (ent);
}
}

View file

@ -1150,9 +1150,7 @@ glsl_R_DrawWorld (void)
R_VisitWorldNodes (&bctx);
if (r_drawentities->int_val) {
entity_t *ent;
for (ent = r_ent_queue; ent; ent = ent->next) {
if (ent->renderer.model->type != mod_brush)
continue;
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) {
R_DrawBrushModel (ent);
}
}

View file

@ -149,9 +149,7 @@ R_RenderEntities (void)
#define RE_LOOP(type_name, Type) \
do { \
begun = 0; \
for (ent = r_ent_queue; ent; ent = ent->next) { \
if (ent->renderer.model->type != mod_##type_name) \
continue; \
for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \
if (!begun) { \
glsl_R_##Type##Begin (); \
begun = 1; \

View file

@ -244,8 +244,6 @@ R_StoreEfrags (const efrag_t *efrag)
break;
default:
Sys_Error ("R_StoreEfrags: Bad entity type %d",
model->type);
}
}
}

View file

@ -55,8 +55,13 @@ typedef struct entity_pool_s {
entity_t entities[ENT_POOL_SIZE];
} entity_pool_t;
entity_t *r_ent_queue;
static entity_t **vis_tail = &r_ent_queue;
entity_t *r_ent_queue[mod_num_types];
static entity_t **vis_tail[mod_num_types] = {
[mod_brush] &r_ent_queue[mod_brush],
[mod_sprite] &r_ent_queue[mod_sprite],
[mod_alias] &r_ent_queue[mod_alias],
[mod_iqm] &r_ent_queue[mod_iqm],
};
static entity_pool_t *entity_pools = 0;
static entity_pool_t **entpool_tail = &entity_pools;
@ -119,16 +124,23 @@ R_FreeAllEntities (void)
void
R_ClearEnts (void)
{
r_ent_queue = 0;
vis_tail = &r_ent_queue;
for (int i = 0; i < mod_num_types; i++) {
r_ent_queue[i] = 0;
vis_tail[i] = &r_ent_queue[i];
}
}
void
R_EnqueueEntity (entity_t *ent)
{
modtype_t type = ent->renderer.model->type;
if (type < 0 || type >= mod_num_types) {
Sys_Error ("R_EnqueueEntity: Bad entity model type %d", type);
}
ent->next = 0;
*vis_tail = ent;
vis_tail = &ent->next;
*vis_tail[type] = ent;
vis_tail[type] = &ent->next;
}
float

View file

@ -340,84 +340,102 @@ R_ViewChanged (void)
D_ViewChanged ();
}
static inline void
draw_sprite_entity (entity_t *ent)
{
VectorSubtract (r_origin, r_entorigin, modelorg);
R_DrawSprite ();
}
static inline void
setup_lighting (alight_t *lighting)
{
float minlight = 0;
int j;
// FIXME: remove and do real lighting
vec3_t dist;
float add;
float lightvec[3] = { -1, 0, 0 };
minlight = max (currententity->renderer.model->min_light,
currententity->renderer.min_light);
// 128 instead of 255 due to clamping below
j = max (R_LightPoint (&r_worldentity.renderer.model->brush, r_entorigin),
minlight * 128);
lighting->ambientlight = j;
lighting->shadelight = j;
lighting->plightvec = lightvec;
for (unsigned lnum = 0; lnum < r_maxdlights; lnum++) {
if (r_dlights[lnum].die >= vr_data.realtime) {
VectorSubtract (r_entorigin, r_dlights[lnum].origin, dist);
add = r_dlights[lnum].radius - VectorLength (dist);
if (add > 0)
lighting->ambientlight += add;
}
}
// clamp lighting so it doesn't overbright as much
if (lighting->ambientlight > 128)
lighting->ambientlight = 128;
if (lighting->ambientlight + lighting->shadelight > 192)
lighting->shadelight = 192 - lighting->ambientlight;
}
static inline void
draw_alias_entity (entity_t *ent)
{
VectorSubtract (r_origin, r_entorigin, modelorg);
// see if the bounding box lets us trivially reject, also
// sets trivial accept status
currententity->visibility.trivial_accept = 0; //FIXME
if (R_AliasCheckBBox ()) {
alight_t lighting;
setup_lighting (&lighting);
R_AliasDrawModel (&lighting);
}
}
static inline void
draw_iqm_entity (entity_t *ent)
{
VectorSubtract (r_origin, r_entorigin, modelorg);
// see if the bounding box lets us trivially reject, also
// sets trivial accept status
currententity->visibility.trivial_accept = 0; //FIXME
alight_t lighting;
setup_lighting (&lighting);
R_IQMDrawModel (&lighting);
}
static void
R_DrawEntitiesOnList (void)
{
int j;
unsigned int lnum;
alight_t lighting;
entity_t *ent;
// FIXME: remove and do real lighting
float lightvec[3] = { -1, 0, 0 };
vec3_t dist;
float add;
float minlight = 0;
if (!r_drawentities->int_val)
return;
for (ent = r_ent_queue; ent; ent = ent->next) {
currententity = ent;
#define RE_LOOP(type_name) \
do { \
for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \
VectorCopy (Transform_GetWorldPosition (ent->transform), \
r_entorigin); \
currententity = ent; \
draw_##type_name##_entity (ent); \
} \
} while (0)
VectorCopy (Transform_GetWorldPosition (currententity->transform),
r_entorigin);
switch (currententity->renderer.model->type) {
case mod_sprite:
VectorSubtract (r_origin, r_entorigin, modelorg);
R_DrawSprite ();
break;
case mod_alias:
case mod_iqm:
VectorSubtract (r_origin, r_entorigin, modelorg);
minlight = max (currententity->renderer.model->min_light,
currententity->renderer.min_light);
// see if the bounding box lets us trivially reject, also
// sets trivial accept status
currententity->visibility.trivial_accept = 0; //FIXME
if (currententity->renderer.model->type == mod_iqm//FIXME
|| R_AliasCheckBBox ()) {
// 128 instead of 255 due to clamping below
j = max (R_LightPoint (&r_worldentity.renderer.model->brush,
r_entorigin), minlight * 128);
lighting.ambientlight = j;
lighting.shadelight = j;
lighting.plightvec = lightvec;
for (lnum = 0; lnum < r_maxdlights; lnum++) {
if (r_dlights[lnum].die >= vr_data.realtime) {
VectorSubtract (r_entorigin,
r_dlights[lnum].origin, dist);
add = r_dlights[lnum].radius - VectorLength (dist);
if (add > 0)
lighting.ambientlight += add;
}
}
// clamp lighting so it doesn't overbright as much
if (lighting.ambientlight > 128)
lighting.ambientlight = 128;
if (lighting.ambientlight + lighting.shadelight > 192)
lighting.shadelight = 192 - lighting.ambientlight;
if (currententity->renderer.model->type == mod_iqm)
R_IQMDrawModel (&lighting);
else
R_AliasDrawModel (&lighting);
}
break;
default:
break;
}
}
RE_LOOP (alias);
RE_LOOP (iqm);
RE_LOOP (sprite);
}
static void
@ -556,90 +574,83 @@ R_DrawBEntitiesOnList (void)
VectorCopy (modelorg, oldorigin);
insubmodel = true;
for (ent = r_ent_queue; ent; ent = ent->next) {
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) {
currententity = ent;
VectorCopy (Transform_GetWorldPosition (currententity->transform),
origin);
switch (currententity->renderer.model->type) {
case mod_brush:
clmodel = currententity->renderer.model;
clmodel = currententity->renderer.model;
// see if the bounding box lets us trivially reject, also
// sets trivial accept status
for (j = 0; j < 3; j++) {
minmaxs[j] = origin[j] + clmodel->mins[j];
minmaxs[3 + j] = origin[j] + clmodel->maxs[j];
}
// see if the bounding box lets us trivially reject, also
// sets trivial accept status
for (j = 0; j < 3; j++) {
minmaxs[j] = origin[j] + clmodel->mins[j];
minmaxs[3 + j] = origin[j] + clmodel->maxs[j];
}
clipflags = R_BmodelCheckBBox (clmodel, minmaxs);
clipflags = R_BmodelCheckBBox (clmodel, minmaxs);
if (clipflags != BMODEL_FULLY_CLIPPED) {
mod_brush_t *brush = &clmodel->brush;
VectorCopy (origin, r_entorigin);
VectorSubtract (r_origin, r_entorigin, modelorg);
if (clipflags != BMODEL_FULLY_CLIPPED) {
mod_brush_t *brush = &clmodel->brush;
VectorCopy (origin, r_entorigin);
VectorSubtract (r_origin, r_entorigin, modelorg);
// FIXME: is this needed?
VectorCopy (modelorg, r_worldmodelorg);
r_pcurrentvertbase = brush->vertexes;
// FIXME: is this needed?
VectorCopy (modelorg, r_worldmodelorg);
r_pcurrentvertbase = brush->vertexes;
// FIXME: stop transforming twice
R_RotateBmodel ();
// FIXME: stop transforming twice
R_RotateBmodel ();
// calculate dynamic lighting for bmodel if it's not an
// instanced model
if (brush->firstmodelsurface != 0) {
vec3_t lightorigin;
// calculate dynamic lighting for bmodel if it's not an
// instanced model
if (brush->firstmodelsurface != 0) {
vec3_t lightorigin;
for (k = 0; k < r_maxdlights; k++) {
if ((r_dlights[k].die < vr_data.realtime) ||
(!r_dlights[k].radius)) continue;
VectorSubtract (r_dlights[k].origin, origin,
lightorigin);
R_RecursiveMarkLights (brush, lightorigin,
&r_dlights[k], k,
brush->nodes
+ brush->hulls[0].firstclipnode);
}
for (k = 0; k < r_maxdlights; k++) {
if ((r_dlights[k].die < vr_data.realtime) ||
(!r_dlights[k].radius)) {
continue;
}
// if the driver wants polygons, deliver those.
// Z-buffering is on at this point, so no clipping to the
// world tree is needed, just frustum clipping
if (r_drawpolys | r_drawculledpolys) {
R_ZDrawSubmodelPolys (clmodel);
VectorSubtract (r_dlights[k].origin, origin, lightorigin);
R_RecursiveMarkLights (brush, lightorigin,
&r_dlights[k], k,
brush->nodes
+ brush->hulls[0].firstclipnode);
}
}
// if the driver wants polygons, deliver those.
// Z-buffering is on at this point, so no clipping to the
// world tree is needed, just frustum clipping
if (r_drawpolys | r_drawculledpolys) {
R_ZDrawSubmodelPolys (clmodel);
} else {
if (currententity->visibility.topnode) {
mnode_t *topnode = currententity->visibility.topnode;
if (topnode->contents >= 0) {
// not a leaf; has to be clipped to the world
// BSP
r_clipflags = clipflags;
R_DrawSolidClippedSubmodelPolygons (clmodel);
} else {
if (currententity->visibility.topnode) {
mnode_t *topnode
= currententity->visibility.topnode;
if (topnode->contents >= 0) {
// not a leaf; has to be clipped to the world
// BSP
r_clipflags = clipflags;
R_DrawSolidClippedSubmodelPolygons (clmodel);
} else {
// falls entirely in one leaf, so we just put
// all the edges in the edge list and let 1/z
// sorting handle drawing order
R_DrawSubmodelPolygons (clmodel, clipflags);
}
}
// falls entirely in one leaf, so we just put
// all the edges in the edge list and let 1/z
// sorting handle drawing order
R_DrawSubmodelPolygons (clmodel, clipflags);
}
// put back world rotation and frustum clipping
// FIXME: R_RotateBmodel should just work off base_vxx
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
VectorCopy (oldorigin, modelorg);
R_TransformFrustum ();
}
break;
default:
break;
}
// put back world rotation and frustum clipping
// FIXME: R_RotateBmodel should just work off base_vxx
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
VectorCopy (oldorigin, modelorg);
R_TransformFrustum ();
}
}

View file

@ -347,85 +347,102 @@ sw32_R_ViewChanged (void)
sw32_D_ViewChanged ();
}
static inline void
draw_sprite_entity (entity_t *ent)
{
VectorSubtract (r_origin, r_entorigin, modelorg);
sw32_R_DrawSprite ();
}
static inline void
setup_lighting (alight_t *lighting)
{
float minlight = 0;
int j;
// FIXME: remove and do real lighting
vec3_t dist;
float add;
float lightvec[3] = { -1, 0, 0 };
minlight = max (currententity->renderer.model->min_light,
currententity->renderer.min_light);
// 128 instead of 255 due to clamping below
j = max (R_LightPoint (&r_worldentity.renderer.model->brush, r_entorigin),
minlight * 128);
lighting->ambientlight = j;
lighting->shadelight = j;
lighting->plightvec = lightvec;
for (unsigned lnum = 0; lnum < r_maxdlights; lnum++) {
if (r_dlights[lnum].die >= vr_data.realtime) {
VectorSubtract (r_entorigin, r_dlights[lnum].origin, dist);
add = r_dlights[lnum].radius - VectorLength (dist);
if (add > 0)
lighting->ambientlight += add;
}
}
// clamp lighting so it doesn't overbright as much
if (lighting->ambientlight > 128)
lighting->ambientlight = 128;
if (lighting->ambientlight + lighting->shadelight > 192)
lighting->shadelight = 192 - lighting->ambientlight;
}
static inline void
draw_alias_entity (entity_t *ent)
{
VectorSubtract (r_origin, r_entorigin, modelorg);
// see if the bounding box lets us trivially reject, also
// sets trivial accept status
currententity->visibility.trivial_accept = 0; //FIXME
if (R_AliasCheckBBox ()) {
alight_t lighting;
setup_lighting (&lighting);
sw32_R_AliasDrawModel (&lighting);
}
}
static inline void
draw_iqm_entity (entity_t *ent)
{
VectorSubtract (r_origin, r_entorigin, modelorg);
// see if the bounding box lets us trivially reject, also
// sets trivial accept status
currententity->visibility.trivial_accept = 0; //FIXME
alight_t lighting;
setup_lighting (&lighting);
sw32_R_IQMDrawModel (&lighting);
}
static void
R_DrawEntitiesOnList (void)
{
int j;
unsigned int lnum;
alight_t lighting;
entity_t *ent;
// FIXME: remove and do real lighting
float lightvec[3] = { -1, 0, 0 };
vec3_t dist;
float add;
float minlight;
if (!r_drawentities->int_val)
return;
for (ent = r_ent_queue; ent; ent = ent->next) {
currententity = ent;
#define RE_LOOP(type_name) \
do { \
for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \
VectorCopy (Transform_GetWorldPosition (ent->transform), \
r_entorigin); \
currententity = ent; \
draw_##type_name##_entity (ent); \
} \
} while (0)
VectorCopy (Transform_GetWorldPosition (currententity->transform),
r_entorigin);
switch (currententity->renderer.model->type) {
case mod_sprite:
VectorSubtract (r_origin, r_entorigin, modelorg);
sw32_R_DrawSprite ();
break;
case mod_alias:
case mod_iqm:
VectorSubtract (r_origin, r_entorigin, modelorg);
minlight = max (currententity->renderer.min_light,
currententity->renderer.model->min_light);
// see if the bounding box lets us trivially reject, also
// sets trivial accept status
currententity->visibility.trivial_accept = 0; //FIXME
if (currententity->renderer.model->type == mod_iqm//FIXME
|| sw32_R_AliasCheckBBox ()) {
// 128 instead of 255 due to clamping below
j = max (R_LightPoint (&r_worldentity.renderer.model->brush,
r_entorigin),
minlight * 128);
lighting.ambientlight = j;
lighting.shadelight = j;
lighting.plightvec = lightvec;
for (lnum = 0; lnum < r_maxdlights; lnum++) {
if (r_dlights[lnum].die >= vr_data.realtime) {
VectorSubtract (r_entorigin,
r_dlights[lnum].origin, dist);
add = r_dlights[lnum].radius - VectorLength (dist);
if (add > 0)
lighting.ambientlight += add;
}
}
// clamp lighting so it doesn't overbright as much
if (lighting.ambientlight > 128)
lighting.ambientlight = 128;
if (lighting.ambientlight + lighting.shadelight > 192)
lighting.shadelight = 192 - lighting.ambientlight;
if (currententity->renderer.model->type == mod_iqm)
sw32_R_IQMDrawModel (&lighting);
else
sw32_R_AliasDrawModel (&lighting);
}
break;
default:
break;
}
}
RE_LOOP (alias);
RE_LOOP (iqm);
RE_LOOP (sprite);
}
static void
@ -563,89 +580,83 @@ R_DrawBEntitiesOnList (void)
VectorCopy (modelorg, oldorigin);
insubmodel = true;
for (ent = r_ent_queue; ent; ent = ent->next) {
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) {
currententity = ent;
VectorCopy (Transform_GetWorldPosition (currententity->transform),
origin);
switch (currententity->renderer.model->type) {
case mod_brush:
clmodel = currententity->renderer.model;
clmodel = currententity->renderer.model;
// see if the bounding box lets us trivially reject, also
// sets trivial accept status
for (j = 0; j < 3; j++) {
minmaxs[j] = origin[j] + clmodel->mins[j];
minmaxs[3 + j] = origin[j] + clmodel->maxs[j];
}
// see if the bounding box lets us trivially reject, also
// sets trivial accept status
for (j = 0; j < 3; j++) {
minmaxs[j] = origin[j] + clmodel->mins[j];
minmaxs[3 + j] = origin[j] + clmodel->maxs[j];
}
clipflags = R_BmodelCheckBBox (clmodel, minmaxs);
clipflags = R_BmodelCheckBBox (clmodel, minmaxs);
if (clipflags != BMODEL_FULLY_CLIPPED) {
mod_brush_t *brush = &clmodel->brush;
VectorCopy (origin, r_entorigin);
VectorSubtract (r_origin, r_entorigin, modelorg);
if (clipflags != BMODEL_FULLY_CLIPPED) {
mod_brush_t *brush = &clmodel->brush;
VectorCopy (origin, r_entorigin);
VectorSubtract (r_origin, r_entorigin, modelorg);
// FIXME: is this needed?
VectorCopy (modelorg, sw32_r_worldmodelorg);
r_pcurrentvertbase = brush->vertexes;
// FIXME: is this needed?
VectorCopy (modelorg, sw32_r_worldmodelorg);
r_pcurrentvertbase = brush->vertexes;
// FIXME: stop transforming twice
sw32_R_RotateBmodel ();
// FIXME: stop transforming twice
sw32_R_RotateBmodel ();
// calculate dynamic lighting for bmodel if it's not an
// instanced model
if (brush->firstmodelsurface != 0) {
vec3_t lightorigin;
// calculate dynamic lighting for bmodel if it's not an
// instanced model
if (brush->firstmodelsurface != 0) {
vec3_t lightorigin;
for (k = 0; k < r_maxdlights; k++) {
if ((r_dlights[k].die < vr_data.realtime) ||
(!r_dlights[k].radius)) continue;
VectorSubtract (r_dlights[k].origin, origin,
lightorigin);
R_RecursiveMarkLights (brush, lightorigin,
&r_dlights[k], k,
brush->nodes
+ brush->hulls[0].firstclipnode);
}
for (k = 0; k < r_maxdlights; k++) {
if ((r_dlights[k].die < vr_data.realtime) ||
(!r_dlights[k].radius)) {
continue;
}
// if the driver wants polygons, deliver those.
// Z-buffering is on at this point, so no clipping to the
// world tree is needed, just frustum clipping
if (sw32_r_drawpolys | sw32_r_drawculledpolys) {
sw32_R_ZDrawSubmodelPolys (clmodel);
VectorSubtract (r_dlights[k].origin, origin, lightorigin);
R_RecursiveMarkLights (brush, lightorigin,
&r_dlights[k], k,
brush->nodes
+ brush->hulls[0].firstclipnode);
}
}
// if the driver wants polygons, deliver those.
// Z-buffering is on at this point, so no clipping to the
// world tree is needed, just frustum clipping
if (sw32_r_drawpolys | sw32_r_drawculledpolys) {
sw32_R_ZDrawSubmodelPolys (clmodel);
} else {
if (currententity->visibility.topnode) {
mnode_t *topnode = currententity->visibility.topnode;
if (topnode->contents >= 0) {
// not a leaf; has to be clipped to the world
// BSP
sw32_r_clipflags = clipflags;
sw32_R_DrawSolidClippedSubmodelPolygons (clmodel);
} else {
if (currententity->visibility.topnode) {
mnode_t *topnode
= currententity->visibility.topnode;
if (topnode->contents >= 0) {
// not a leaf; has to be clipped to the world
// BSP
sw32_r_clipflags = clipflags;
sw32_R_DrawSolidClippedSubmodelPolygons (clmodel);
} else {
// falls entirely in one leaf, so we just put
// all the edges in the edge list and let 1/z
// sorting handle drawing order
sw32_R_DrawSubmodelPolygons (clmodel, clipflags);
}
}
// falls entirely in one leaf, so we just put
// all the edges in the edge list and let 1/z
// sorting handle drawing order
sw32_R_DrawSubmodelPolygons (clmodel, clipflags);
}
// put back world rotation and frustum clipping
// FIXME: sw32_R_RotateBmodel should just work off base_vxx
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
VectorCopy (oldorigin, modelorg);
sw32_R_TransformFrustum ();
}
break;
default:
break;
}
// put back world rotation and frustum clipping
// FIXME: sw32_R_RotateBmodel should just work off base_vxx
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
VectorCopy (base_modelorg, modelorg);
VectorCopy (oldorigin, modelorg);
sw32_R_TransformFrustum ();
}
}

View file

@ -1040,9 +1040,7 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame)
R_VisitWorldNodes (brush, ctx);
if (r_drawentities->int_val) {
entity_t *ent;
for (ent = r_ent_queue; ent; ent = ent->next) {
if (ent->renderer.model->type != mod_brush)
continue;
for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) {
R_DrawBrushModel (ent, ctx);
}
}

View file

@ -87,9 +87,7 @@ Vulkan_RenderEntities (qfv_renderframe_t *rFrame)
do { \
entity_t *ent; \
int begun = 0; \
for (ent = r_ent_queue; ent; ent = ent->next) { \
if (ent->renderer.model->type != mod_##type_name) \
continue; \
for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \
if (!begun) { \
Vulkan_##Type##Begin (rFrame); \
begun = 1; \