cvar_t r_glsl_vertextextureblend_usebothalphas = {CF_CLIENT | CF_ARCHIVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
+// FIXME: This cvar would grow to a ridiculous size after several launches and clean exits when used during surface sorting.
cvar_t r_framedatasize = {CF_CLIENT | CF_ARCHIVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
{
r_texture_numcubemaps = 0;
//r_texture_fogintensity = NULL;
memset(&r_fb, 0, sizeof(r_fb));
- R_GLSL_Restart_f(&cmd_client);
+ R_GLSL_Restart_f(cmd_local);
r_glsl_permutation = NULL;
memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
R_Particles_Init();
R_Explosion_Init();
R_LightningBeams_Init();
+ CL_MeshEntities_Init();
Mod_RenderInit();
}
-int R_CullBox(const vec3_t mins, const vec3_t maxs)
+static void R_GetCornerOfBox(vec3_t out, const vec3_t mins, const vec3_t maxs, int signbits)
{
- int i;
- mplane_t *p;
- if (r_trippy.integer)
- return false;
- for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
- {
- p = r_refdef.view.frustum + i;
- switch(p->signbits)
- {
- default:
- case 0:
- if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
- return true;
- break;
- case 1:
- if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
- return true;
- break;
- case 2:
- if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
- return true;
- break;
- case 3:
- if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
- return true;
- break;
- case 4:
- if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
- return true;
- break;
- case 5:
- if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
- return true;
- break;
- case 6:
- if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
- return true;
- break;
- case 7:
- if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
- return true;
- break;
- }
- }
- return false;
+ out[0] = ((signbits & 1) ? mins : maxs)[0];
+ out[1] = ((signbits & 2) ? mins : maxs)[1];
+ out[2] = ((signbits & 4) ? mins : maxs)[2];
}
-int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
+static qbool _R_CullBox(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes, int ignore)
{
int i;
const mplane_t *p;
+ vec3_t corner;
if (r_trippy.integer)
return false;
for (i = 0;i < numplanes;i++)
{
+ if(i == ignore)
+ continue;
p = planes + i;
- switch(p->signbits)
- {
- default:
- case 0:
- if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
- return true;
- break;
- case 1:
- if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
- return true;
- break;
- case 2:
- if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
- return true;
- break;
- case 3:
- if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
- return true;
- break;
- case 4:
- if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
- return true;
- break;
- case 5:
- if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
- return true;
- break;
- case 6:
- if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
- return true;
- break;
- case 7:
- if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
- return true;
- break;
- }
+ R_GetCornerOfBox(corner, mins, maxs, p->signbits);
+ if (DotProduct(p->normal, corner) < p->dist)
+ return true;
}
return false;
}
+qbool R_CullFrustum(const vec3_t mins, const vec3_t maxs)
+{
+ // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
+ return _R_CullBox(mins, maxs, r_refdef.view.numfrustumplanes, r_refdef.view.frustum, 4);
+}
+
+qbool R_CullBox(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
+{
+ // nothing to ignore
+ return _R_CullBox(mins, maxs, numplanes, planes, -1);
+}
+
//==================================================================================
// LadyHavoc: this stores temporary data used within the same frame
if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
return true;
+ VectorCopy(eye, start);
// try specific positions in the box first - note that these can be cached
if (r_cullentities_trace_entityocclusion.integer)
{
for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
{
trace_t trace;
- VectorCopy(eye, start);
end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
return true;
}
}
- else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
- return true;
+ else
+ {
+ // try center
+ VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
+ if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
+ return true;
+ }
// try various random positions
for (j = 0; j < numsamples; j++)
continue;
}
if (!(ent->flags & renderimask))
- if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
+ if (!R_CullFrustum(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
r_refdef.viewcache.entityvisible[i] = true;
}
{
ent = r_refdef.scene.entities[i];
if (!(ent->flags & renderimask))
- if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
+ if (!R_CullFrustum(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
r_refdef.viewcache.entityvisible[i] = true;
}
}
rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
if(R_CompileShader_CheckStaticParms())
- R_GLSL_Restart_f(&cmd_client);
+ R_GLSL_Restart_f(cmd_local);
if (!r_drawentities.integer)
r_refdef.scene.numentities = 0;
for (i = 0; i < prog->num_edicts; i++)
{
edict = PRVM_EDICT_NUM(i);
- if (edict->priv.server->free)
+ if (edict->free)
continue;
// exclude the following for now, as they don't live in world coordinate space and can't be solid:
if (PRVM_gameedictedict(edict, tag_entity) != 0)
GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
{
- if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
+ if (cullbox && R_CullFrustum(bihleaf->mins, bihleaf->maxs))
continue;
switch (bihleaf->type)
{
}
else if (ui)
{
- // for ui we have to preserve the order of surfaces (not using sortedmodelsurfaces)
+ // for ui we have to preserve the order of surfaces (not using modelsurfaces_sorted)
for (i = model->submodelsurfaces_start; i < model->submodelsurfaces_end; i++)
r_surfacelist[numsurfacelist++] = surfaces + i;
}