#include "csprogs.h"
#include "cl_video.h"
#include "dpsoftrast.h"
+#include "cl_collision.h"
#ifdef SUPPORTD3D
#include <d3d9.h>
cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
+cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%, 10 = 100%)" };
cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
+cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
+cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"};
cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
/// hash lookup data
struct r_glsl_permutation_s *hashnext;
unsigned int mode;
- unsigned int permutation;
+ dpuint64 permutation;
/// indicates if we have tried compiling this permutation already
qboolean compiled;
shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
else \
shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
-static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
+static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
{
shaderstaticparms_count = 0;
/// storage for permutations linked in the hash table
memexpandablearray_t r_glsl_permutationarray;
-static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
+static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
{
//unsigned int hashdepth = 0;
unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
}
-static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
+static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
{
int i;
int ubibind;
geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
}
+ // if we can do #version 120, we should (this adds the invariant keyword)
+ else if(vid.support.glshaderversion >= 120)
+ {
+ vertstrings_list[vertstrings_count++] = "#version 120\n";
+ geomstrings_list[geomstrings_count++] = "#version 120\n";
+ fragstrings_list[fragstrings_count++] = "#version 120\n";
+ vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
+ geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
+ fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
+ }
+ // GLES also adds several things from GLSL120
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GLES2:
+ vertstrings_list[vertstrings_count++] = "#define GLES\n";
+ geomstrings_list[geomstrings_count++] = "#define GLES\n";
+ fragstrings_list[fragstrings_count++] = "#define GLES\n";
+ break;
+ default:
+ break;
+ }
// the first pretext is which type of shader to compile as
// (later these will all be bound together as a program object)
// now add all the permutation pretexts
for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
{
- if (permutation & (1<<i))
+ if (permutation & (1ll<<i))
{
vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
Mem_Free(sourcestring);
}
-static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
+static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
{
r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
if (r_glsl_permutation != perm)
for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
{
// reduce i more quickly whenever it would not remove any bits
- int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
+ dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
if (!(permutation & j))
continue;
permutation -= j;
/// hash lookup data
struct r_hlsl_permutation_s *hashnext;
unsigned int mode;
- unsigned int permutation;
+ dpuint64 permutation;
/// indicates if we have tried compiling this permutation already
qboolean compiled;
/// storage for permutations linked in the hash table
memexpandablearray_t r_hlsl_permutationarray;
-static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
+static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
{
//unsigned int hashdepth = 0;
unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
}
-static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
+static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
{
int i;
shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
// now add all the permutation pretexts
for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
{
- if (permutation & (1<<i))
+ if (permutation & (1ll<<i))
{
vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
-void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
+void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
{
r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
if (r_hlsl_permutation != perm)
for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
{
// reduce i more quickly whenever it would not remove any bits
- int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
+ dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
if (!(permutation & j))
continue;
permutation -= j;
}
#endif
-static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
+static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
{
DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
{
- unsigned int permutation = 0;
+ dpuint64 permutation = 0;
if (r_trippy.integer && !notrippy)
permutation |= SHADERPERMUTATION_TRIPPY;
permutation |= SHADERPERMUTATION_VIEWTINT;
void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
{
- unsigned int permutation = 0;
+ dpuint64 permutation = 0;
if (r_trippy.integer && !notrippy)
permutation |= SHADERPERMUTATION_TRIPPY;
if (depthrgb)
// combination of texture, entity, light source, and fogging, only use the
// minimum features necessary to avoid wasting rendering time in the
// fragment shader on features that are not being used
- unsigned int permutation = 0;
+ dpuint64 permutation = 0;
unsigned int mode = 0;
int blendfuncflags;
static float dummy_colormod[3] = {1, 1, 1};
// combination of texture, entity, light source, and fogging, only use the
// minimum features necessary to avoid wasting rendering time in the
// fragment shader on features that are not being used
- unsigned int permutation = 0;
+ dpuint64 permutation = 0;
unsigned int mode = 0;
const float *lightcolorbase = rtlight->currentcolor;
float ambientscale = rtlight->ambientscale;
Cvar_RegisterVariable(&r_transparent_useplanardistance);
Cvar_RegisterVariable(&r_showoverdraw);
Cvar_RegisterVariable(&r_showbboxes);
+ Cvar_RegisterVariable(&r_showbboxes_client);
Cvar_RegisterVariable(&r_showsurfaces);
Cvar_RegisterVariable(&r_showtris);
Cvar_RegisterVariable(&r_shownormals);
Cvar_RegisterVariable(&r_draw2d);
Cvar_RegisterVariable(&r_drawworld);
Cvar_RegisterVariable(&r_cullentities_trace);
+ Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
Cvar_RegisterVariable(&r_cullentities_trace_samples);
Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
Cvar_RegisterVariable(&r_cullentities_trace_delay);
+ Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
Cvar_RegisterVariable(&r_sortentities);
Cvar_RegisterVariable(&r_drawviewmodel);
Cvar_RegisterVariable(&r_drawexteriormodel);
while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
{
// emergency - we ran out of space, allocate more memory
- newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
+ // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
+ newvalue = r_framedatasize.value * 2.0f;
+ // upper bound based on architecture - if we try to allocate more than this we could overflow, better to loop until we error out on allocation failure
+ if (sizeof(size_t) >= 8)
+ newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
+ else
+ newvalue = bound(0.25f, newvalue, (float)(1 << 10));
// this might not be a growing it, but we'll allocate another buffer every time
Cvar_SetValueQuick(&r_framedatasize, newvalue);
R_FrameData_Resize(true);
}
}
-#define MAX_LINEOFSIGHTTRACES 64
-
-static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
+qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
{
int i;
+ vec3_t eyemins, eyemaxs;
vec3_t boxmins, boxmaxs;
vec3_t start;
vec3_t end;
dp_model_t *model = r_refdef.scene.worldmodel;
+ static vec3_t positions[] = {
+ { 0.5f, 0.5f, 0.5f },
+ { 0.0f, 0.0f, 0.0f },
+ { 0.0f, 0.0f, 1.0f },
+ { 0.0f, 1.0f, 0.0f },
+ { 0.0f, 1.0f, 1.0f },
+ { 1.0f, 0.0f, 0.0f },
+ { 1.0f, 0.0f, 1.0f },
+ { 1.0f, 1.0f, 0.0f },
+ { 1.0f, 1.0f, 1.0f },
+ };
+
+ // sample count can be set to -1 to skip this logic, for flicker-prone objects
+ if (numsamples < 0)
+ return true;
- if (!model || !model->brush.TraceLineOfSight)
+ // view origin is not used for culling in portal/reflection/refraction renders or isometric views
+ if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
return true;
+ if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
+ return true;
+
+ // expand the eye box a little
+ eyemins[0] = eye[0] - eyejitter;
+ eyemaxs[0] = eye[0] + eyejitter;
+ eyemins[1] = eye[1] - eyejitter;
+ eyemaxs[1] = eye[1] + eyejitter;
+ eyemins[2] = eye[2] - eyejitter;
+ eyemaxs[2] = eye[2] + eyejitter;
// expand the box a little
- boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
- boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
- boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
- boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
- boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
- boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
-
- // return true if eye is inside enlarged box
- if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
+ boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
+ boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
+ boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
+ boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
+ boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
+ boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
+
+ // return true if eye overlaps enlarged box
+ if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
return true;
- // try center
- VectorCopy(eye, start);
- VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
- if (model->brush.TraceLineOfSight(model, start, end))
+ // 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++)
+ {
+ 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];
+ //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
+ trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
+ // not picky - if the trace ended anywhere in the box we're good
+ if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
+ return true;
+ }
+ }
+ else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
return true;
// try various random positions
- for (i = 0;i < numsamples;i++)
+ for (i = 0; i < numsamples; i++)
{
+ VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
- if (model->brush.TraceLineOfSight(model, start, end))
+ if (r_cullentities_trace_entityocclusion.integer)
+ {
+ trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
+ // not picky - if the trace ended anywhere in the box we're good
+ if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
+ return true;
+ }
+ else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
return true;
}
r_refdef.viewcache.entityvisible[i] = true;
}
}
- if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
- // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
+ if (r_cullentities_trace.integer)
{
for (i = 0;i < r_refdef.scene.numentities;i++)
{
if (!r_refdef.viewcache.entityvisible[i])
continue;
ent = r_refdef.scene.entities[i];
- if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
+ if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
{
- samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
- if (samples < 0)
- continue; // temp entities do pvs only
- if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
+ samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
+ if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
ent->last_trace_visibility = realtime;
- if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
+ if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
r_refdef.viewcache.entityvisible[i] = 0;
}
}
r_fb.bloomindex = 0;
R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
R_SetViewport(&r_fb.bloomviewport);
+ GL_CullFace(GL_NONE);
GL_DepthTest(false);
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_Color(colorscale, colorscale, colorscale, 1);
static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
{
- unsigned int permutation;
+ dpuint64 permutation;
float uservecs[4][4];
R_EntityMatrix(&identitymatrix);
extern cvar_t cl_locs_show;
static void R_DrawLocs(void);
-static void R_DrawEntityBBoxes(void);
+static void R_DrawEntityBBoxes(prvm_prog_t *prog);
static void R_DrawModelDecals(void);
extern cvar_t cl_decals_newsystem;
extern qboolean r_shadow_usingdeferredprepass;
R_DrawExplosions();
if (r_timereport_active)
R_TimeReport("explosions");
-
- R_DrawLightningBeams();
- if (r_timereport_active)
- R_TimeReport("lightning");
}
if (cl.csqc_loaded)
R_TimeReport("portals");
}
+ if (r_showbboxes_client.value > 0)
+ {
+ R_DrawEntityBBoxes(CLVM_prog);
+ if (r_timereport_active)
+ R_TimeReport("clbboxes");
+ }
if (r_showbboxes.value > 0)
{
- R_DrawEntityBBoxes();
+ R_DrawEntityBBoxes(SVVM_prog);
if (r_timereport_active)
- R_TimeReport("bboxes");
+ R_TimeReport("svbboxes");
}
}
1, 0, 2, 1, 2, 3,
};
+#define BBOXEDGES 13
+static const float bboxedges[BBOXEDGES][6] =
+{
+ // whole box
+ { 0, 0, 0, 1, 1, 1 },
+ // bottom edges
+ { 0, 0, 0, 0, 1, 0 },
+ { 0, 0, 0, 1, 0, 0 },
+ { 0, 1, 0, 1, 1, 0 },
+ { 1, 0, 0, 1, 1, 0 },
+ // top edges
+ { 0, 0, 1, 0, 1, 1 },
+ { 0, 0, 1, 1, 0, 1 },
+ { 0, 1, 1, 1, 1, 1 },
+ { 1, 0, 1, 1, 1, 1 },
+ // vertical edges
+ { 0, 0, 0, 0, 0, 1 },
+ { 1, 0, 0, 1, 0, 1 },
+ { 0, 1, 0, 0, 1, 1 },
+ { 1, 1, 0, 1, 1, 1 },
+};
+
static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
{
- int i;
- float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
+ int numvertices = BBOXEDGES * 8;
+ float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
+ int numtriangles = BBOXEDGES * 12;
+ unsigned short elements[BBOXEDGES * 36];
+ int i, edge;
+ float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
RSurf_ActiveWorldEntity();
GL_DepthMask(false);
GL_DepthRange(0, 1);
GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
-// R_Mesh_ResetTextureState();
- vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
- vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
- vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
- vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
- vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
- vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
- vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
- vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
- R_FillColors(color4f, 8, cr, cg, cb, ca);
+ for (edge = 0; edge < BBOXEDGES; edge++)
+ {
+ for (i = 0; i < 3; i++)
+ {
+ edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
+ edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
+ }
+ vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
+ vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
+ vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
+ vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
+ vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
+ vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
+ vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
+ vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
+ for (i = 0; i < 36; i++)
+ elements[edge * 36 + i] = edge * 8 + bboxelements[i];
+ }
+ R_FillColors(color4f, numvertices, cr, cg, cb, ca);
if (r_refdef.fogenabled)
{
- for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
+ for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
{
f1 = RSurf_FogVertex(v);
f2 = 1 - f1;
c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
}
}
- R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
+ R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
R_Mesh_ResetTextureState();
R_SetupShader_Generic_NoTexture(false, false);
- R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
+ R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
}
static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
- prvm_prog_t *prog = SVVM_prog;
+ // hacky overloading of the parameters
+ prvm_prog_t *prog = (prvm_prog_t *)rtlight;
int i;
float color[4];
prvm_edict_t *edict;
- // this function draws bounding boxes of server entities
- if (!sv.active)
- return;
-
GL_CullFace(GL_NONE);
R_SetupShader_Generic_NoTexture(false, false);
case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
default: Vector4Set(color, 0, 0, 0, 0.50);break;
}
- color[3] *= r_showbboxes.value;
+ if (prog == CLVM_prog)
+ color[3] *= r_showbboxes_client.value;
+ else
+ color[3] *= r_showbboxes.value;
color[3] = bound(0, color[3], 1);
GL_DepthTest(!r_showdisabledepthtest.integer);
- GL_CullFace(r_refdef.view.cullface_front);
R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
}
}
-static void R_DrawEntityBBoxes(void)
+static void R_DrawEntityBBoxes(prvm_prog_t *prog)
{
int i;
prvm_edict_t *edict;
vec3_t center;
- prvm_prog_t *prog = SVVM_prog;
- // this function draws bounding boxes of server entities
- if (!sv.active)
+ if (prog == NULL)
return;
- for (i = 0;i < prog->num_edicts;i++)
+ for (i = 0; i < prog->num_edicts; i++)
{
edict = PRVM_EDICT_NUM(i);
if (edict->priv.server->free)
continue;
// exclude the following for now, as they don't live in world coordinate space and can't be solid:
- if(PRVM_serveredictedict(edict, tag_entity) != 0)
+ if (PRVM_serveredictedict(edict, tag_entity) != 0)
continue;
- if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
+ if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
continue;
VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
- R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
+ R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
}
}