cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
+cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
+cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
+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_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
-cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
+cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
typedef struct r_glsl_bloomshader_s
" //\n"
" // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
" // provide significant illumination, large = slow = pain.\n"
-" color.rgb *= myhalf(max(1.0 - dot(CubeVector, CubeVector), 0.0));\n"
+"// color.rgb *= myhalf(max(1.0 - dot(CubeVector, CubeVector), 0.0));\n"
+" color.rgb *= myhalf(max(2.0 - 2.0 * length(CubeVector), 0.0) / (1 + dot(CubeVector, CubeVector)));\n"
"\n"
"\n"
"\n"
{
r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
- Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
+ Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
FOG_registercvars(); // FIXME: move this fog stuff to client?
Cvar_RegisterVariable(&r_nearclip);
Cvar_RegisterVariable(&r_showsurfaces);
Cvar_RegisterVariable(&r_showdisabledepthtest);
Cvar_RegisterVariable(&r_drawportals);
Cvar_RegisterVariable(&r_drawentities);
+ Cvar_RegisterVariable(&r_cullentities_trace);
+ Cvar_RegisterVariable(&r_cullentities_trace_samples);
+ Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
+ Cvar_RegisterVariable(&r_cullentities_trace_delay);
Cvar_RegisterVariable(&r_drawviewmodel);
Cvar_RegisterVariable(&r_speeds);
Cvar_RegisterVariable(&r_fullbrights);
return false;
}
+int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
+{
+ int i;
+ const mplane_t *p;
+ for (i = 0;i < numplanes;i++)
+ {
+ 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;
+ }
+ }
+ return false;
+}
+
//==================================================================================
static void R_UpdateEntityLighting(entity_render_t *ent)
ent = r_refdef.entities[i];
r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
}
+ if(r_cullentities_trace.integer)
+ {
+ for (i = 0;i < r_refdef.numentities;i++)
+ {
+ ent = r_refdef.entities[i];
+ if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->model && (ent->model->name[0] == '*')))
+ {
+ if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
+ ent->last_trace_visibility = realtime;
+ if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
+ r_viewcache.entityvisible[i] = 0;
+ }
+ }
+ }
}
else
{
static void R_View_SetFrustum(void)
{
+ double slopex, slopey;
+
// break apart the view matrix into vectors for various purposes
Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
VectorNegate(r_view.left, r_view.right);
- VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
- VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
- VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
- VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
+ slopex = 1.0 / r_view.frustum_x;
+ slopey = 1.0 / r_view.frustum_y;
+ VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
+ VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
+ VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
+ VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
VectorCopy(r_view.forward, r_view.frustum[4].normal);
VectorNormalize(r_view.frustum[0].normal);
VectorNormalize(r_view.frustum[1].normal);
PlaneClassify(&r_view.frustum[3]);
PlaneClassify(&r_view.frustum[4]);
+ // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
+ VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
+ VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
+ VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
+ VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
+
// LordHavoc: note to all quake engine coders, Quake had a special case
// for 90 degrees which assumed a square view (wrong), so I removed it,
// Quake2 has it disabled as well.
extern void R_DrawLightningBeams (void);
extern void VM_CL_AddPolygonsToMeshQueue (void);
extern void R_DrawPortals (void);
+extern cvar_t cl_locs_show;
+static void R_DrawLocs(void);
void R_RenderScene(void)
{
// don't let sound skip if going slow
}
VM_CL_AddPolygonsToMeshQueue();
+ if (cl_locs_show.integer)
+ {
+ R_DrawLocs();
+ if (r_timereport_active)
+ R_TimeReport("showlocs");
+ }
+
if (r_drawportals.integer)
{
R_DrawPortals();
GL_DepthMask(true);
}
GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
- GL_CullFace((ent->flags & RENDER_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
+ GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
R_Mesh_VertexPointer(nomodelvertex3f);
if (r_refdef.fogenabled)
{
t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
else if (t->currentalpha < 1)
t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW;
- if (ent->flags & RENDER_NOCULLFACE)
- t->currentmaterialflags |= MATERIALFLAG_NOSHADOW;
+ if (ent->effects & EF_DOUBLESIDED)
+ t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
if (ent->effects & EF_NODEPTHTEST)
t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_NOSHADOW;
if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
texture_t *rsurface_texture;
qboolean rsurface_uselightmaptexture;
rsurfmode_t rsurface_mode;
-texture_t *rsurface_glsl_texture;
-qboolean rsurface_glsl_uselightmap;
int rsurface_lightmode; // 0 = lightmap or fullbright, 1 = color array from q3bsp, 2 = vertex shaded model
void RSurf_CleanUp(void)
rsurface_mode = RSURFMODE_NONE;
rsurface_uselightmaptexture = false;
rsurface_texture = NULL;
- rsurface_glsl_texture = NULL;
- rsurface_glsl_uselightmap = false;
}
-void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
+void RSurf_ActiveWorldEntity(void)
+{
+ RSurf_CleanUp();
+ rsurface_entity = r_refdef.worldentity;
+ rsurface_model = r_refdef.worldmodel;
+ if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
+ R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
+ R_Mesh_Matrix(&identitymatrix);
+ VectorCopy(r_view.origin, rsurface_modelorg);
+ rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
+ rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
+ rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
+ rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
+ rsurface_generatedvertex = false;
+ rsurface_vertex3f = rsurface_modelvertex3f;
+ rsurface_svector3f = rsurface_modelsvector3f;
+ rsurface_tvector3f = rsurface_modeltvector3f;
+ rsurface_normal3f = rsurface_modelnormal3f;
+}
+
+void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
{
RSurf_CleanUp();
- Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
rsurface_entity = ent;
rsurface_model = ent->model;
if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
R_Mesh_Matrix(&ent->matrix);
Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
- if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
+ if (rsurface_model->surfmesh.isanimated && (rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0))
{
if (wanttangents)
{
}
else if (r_batchmode.integer == 1)
{
+#if 0
+ Con_Printf("%s batch sizes ignoring lightmap:", rsurface_texture->name);
+ for (i = 0;i < texturenumsurfaces;i = j)
+ {
+ surface = texturesurfacelist[i];
+ for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
+ if (texturesurfacelist[j] != surface2)
+ break;
+ Con_Printf(" %i", j - i);
+ }
+ Con_Printf("\n");
+ Con_Printf("%s batch sizes honoring lightmap:", rsurface_texture->name);
+#endif
for (i = 0;i < texturenumsurfaces;i = j)
{
surface = texturesurfacelist[i];
for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
break;
+#if 0
+ Con_Printf(" %i", j - i);
+#endif
surface2 = texturesurfacelist[j-1];
numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
GL_LockArrays(surface->num_firstvertex, numvertices);
R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
}
+#if 0
+ Con_Printf("\n");
+#endif
}
else
{
}
}
-static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
+static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
{
int texturesurfaceindex;
int i;
float f;
float *v, *c, *c2;
- // TODO: optimize
- if (lightmode >= 2)
- {
- // model lighting
- vec3_t ambientcolor;
- vec3_t diffusecolor;
- vec3_t lightdir;
- VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
- ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
- ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
- ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
- diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
- diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
- diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
- if (VectorLength2(diffusecolor) > 0)
- {
- // generate color arrays for the surfaces in this list
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ if (rsurface_lightmapcolor4f)
+ {
+ // generate color arrays for the surfaces in this list
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
+ for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- int numverts = surface->num_vertices;
- v = rsurface_vertex3f + 3 * surface->num_firstvertex;
- c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
- c = rsurface_array_color4f + 4 * surface->num_firstvertex;
- // q3-style directional shading
- for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
- {
- if ((f = DotProduct(c2, lightdir)) > 0)
- VectorMA(ambientcolor, f, diffusecolor, c);
- else
- VectorCopy(ambientcolor, c);
- c[3] = a;
- }
+ f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
+ c2[0] = c[0] * f;
+ c2[1] = c[1] * f;
+ c2[2] = c[2] * f;
+ c2[3] = c[3];
}
- r = 1;
- g = 1;
- b = 1;
- a = 1;
- applycolor = false;
- rsurface_lightmapcolor4f = rsurface_array_color4f;
}
- else
+ }
+ else
+ {
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
{
- r = ambientcolor[0];
- g = ambientcolor[1];
- b = ambientcolor[2];
- rsurface_lightmapcolor4f = NULL;
+ const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
+ for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
+ {
+ f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
+ c2[0] = f;
+ c2[1] = f;
+ c2[2] = f;
+ c2[3] = 1;
+ }
}
}
- else if (lightmode >= 1 || !rsurface_uselightmaptexture)
+ rsurface_lightmapcolor4f = rsurface_array_color4f;
+}
+
+static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
+{
+ int texturesurfaceindex;
+ int i;
+ float *c, *c2;
+ if (!rsurface_lightmapcolor4f)
+ return;
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
{
- if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
+ const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
+ for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
{
- // generate color arrays for the surfaces in this list
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ c2[0] = c[0] * r;
+ c2[1] = c[1] * g;
+ c2[2] = c[2] * b;
+ c2[3] = c[3] * a;
+ }
+ }
+ rsurface_lightmapcolor4f = rsurface_array_color4f;
+}
+
+static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
+{
+ // TODO: optimize
+ rsurface_lightmapcolor4f = NULL;
+ if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
+ if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
+ R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
+ GL_Color(r, g, b, a);
+ RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
+}
+
+static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
+{
+ // TODO: optimize applyfog && applycolor case
+ // just apply fog if necessary, and tint the fog color array if necessary
+ rsurface_lightmapcolor4f = NULL;
+ if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
+ if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
+ R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
+ GL_Color(r, g, b, a);
+ RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+}
+
+static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
+{
+ int texturesurfaceindex;
+ int i;
+ float *c;
+ // TODO: optimize
+ if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
+ {
+ // generate color arrays for the surfaces in this list
+ for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ {
+ const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
+ for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
+ if (surface->lightmapinfo->samples)
{
- if (surface->lightmapinfo->samples)
+ const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
+ float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
+ VectorScale(lm, scale, c);
+ if (surface->lightmapinfo->styles[1] != 255)
{
- const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
- float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
- VectorScale(lm, scale, c);
- if (surface->lightmapinfo->styles[1] != 255)
+ int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
+ lm += size3;
+ scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
+ VectorMA(c, scale, lm, c);
+ if (surface->lightmapinfo->styles[2] != 255)
{
- int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
lm += size3;
- scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
+ scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
VectorMA(c, scale, lm, c);
- if (surface->lightmapinfo->styles[2] != 255)
+ if (surface->lightmapinfo->styles[3] != 255)
{
lm += size3;
- scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
+ scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
VectorMA(c, scale, lm, c);
- if (surface->lightmapinfo->styles[3] != 255)
- {
- lm += size3;
- scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
- VectorMA(c, scale, lm, c);
- }
}
}
}
- else
- VectorClear(c);
- c[3] = 1;
- }
- }
- rsurface_lightmapcolor4f = rsurface_array_color4f;
- }
- else
- rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
- }
- else
- {
- // just lightmap it
- rsurface_lightmapcolor4f = NULL;
- }
- if (applyfog)
- {
- if (rsurface_lightmapcolor4f)
- {
- // generate color arrays for the surfaces in this list
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
- {
- f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
- c2[0] = c[0] * f;
- c2[1] = c[1] * f;
- c2[2] = c[2] * f;
- c2[3] = c[3];
- }
- }
- }
- else
- {
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
- {
- f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
- c2[0] = f;
- c2[1] = f;
- c2[2] = f;
- c2[3] = 1;
}
+ else
+ VectorClear(c);
+ c[3] = 1;
}
}
rsurface_lightmapcolor4f = rsurface_array_color4f;
}
- if (applycolor && rsurface_lightmapcolor4f)
+ else
+ rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
+ if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
+ if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
+ R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
+ GL_Color(r, g, b, a);
+ RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+}
+
+static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
+{
+ int texturesurfaceindex;
+ int i;
+ float f;
+ float *v, *c, *c2;
+ vec3_t ambientcolor;
+ vec3_t diffusecolor;
+ vec3_t lightdir;
+ // TODO: optimize
+ // model lighting
+ VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
+ ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
+ ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
+ ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
+ diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
+ diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
+ diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
+ if (VectorLength2(diffusecolor) > 0)
{
+ // generate color arrays for the surfaces in this list
for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
{
const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
+ int numverts = surface->num_vertices;
+ v = rsurface_vertex3f + 3 * surface->num_firstvertex;
+ c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
+ c = rsurface_array_color4f + 4 * surface->num_firstvertex;
+ // q3-style directional shading
+ for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
{
- c2[0] = c[0] * r;
- c2[1] = c[1] * g;
- c2[2] = c[2] * b;
- c2[3] = c[3] * a;
+ if ((f = DotProduct(c2, lightdir)) > 0)
+ VectorMA(ambientcolor, f, diffusecolor, c);
+ else
+ VectorCopy(ambientcolor, c);
+ c[3] = a;
}
}
+ r = 1;
+ g = 1;
+ b = 1;
+ a = 1;
+ applycolor = false;
rsurface_lightmapcolor4f = rsurface_array_color4f;
}
+ else
+ {
+ r = ambientcolor[0];
+ g = ambientcolor[1];
+ b = ambientcolor[2];
+ rsurface_lightmapcolor4f = NULL;
+ }
+ if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
+ if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
GL_Color(r, g, b, a);
- if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
- RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
- else
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
}
static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
{
GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
- GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
+ GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
if (rsurface_mode != RSURFMODE_SHOWSURFACES)
{
rsurface_mode = RSURFMODE_SHOWSURFACES;
R_Mesh_Matrix(&rsurface_entity->matrix);
}
GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
- GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
+ GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
GL_DepthMask(true);
// LordHavoc: HalfLife maps have freaky skypolys so don't use
// skymasking on them, and Quake3 never did sky masking (unlike
if (rsurface_mode != RSURFMODE_GLSL)
{
rsurface_mode = RSURFMODE_GLSL;
- rsurface_glsl_texture = NULL;
- rsurface_glsl_uselightmap = false;
R_Mesh_ResetTextureState();
}
- if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != rsurface_uselightmaptexture)
- {
- rsurface_glsl_texture = rsurface_texture;
- rsurface_glsl_uselightmap = rsurface_uselightmaptexture;
- R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2);
- //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2, false);
- //if (r_glsl_deluxemapping.integer)
- // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2, true);
- R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
- R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
- RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
- R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
- R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
- R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
- if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
- {
- R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
- if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
- R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
- R_Mesh_ColorPointer(NULL);
- }
- else if (rsurface_uselightmaptexture)
- {
- R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
- if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
- R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
- R_Mesh_ColorPointer(NULL);
- }
- else
- {
- R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
- if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
- R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
- R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
- }
- }
- else
- RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
+
+ R_SetupSurfaceShader(vec3_origin, rsurface_lightmode == 2);
if (!r_glsl_permutation)
return;
+
+ if (rsurface_lightmode == 2)
+ RSurf_PrepareVerticesForBatch(true, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
+ else
+ RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal, r_glsl_permutation->loc_Texture_Normal, texturenumsurfaces, texturesurfacelist);
+ R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
+ R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
+ R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
+ R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
+ R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
+
+ if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
+ {
+ R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
+ if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
+ R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
+ R_Mesh_ColorPointer(NULL);
+ }
+ else if (rsurface_uselightmaptexture)
+ {
+ R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
+ if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
+ R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
+ R_Mesh_ColorPointer(NULL);
+ }
+ else
+ {
+ R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
+ if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
+ R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
+ R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
+ }
+
if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
else
m.texrgbscale[1] = layertexrgbscale;
m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
R_Mesh_TextureState(&m);
- RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], rsurface_lightmode, applycolor, applyfog);
+ if (rsurface_lightmode == 2)
+ RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
+ else if (rsurface_uselightmaptexture)
+ RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
+ else
+ RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
break;
case TEXTURELAYERTYPE_TEXTURE:
memset(&m, 0, sizeof(m));
m.texrgbscale[0] = layertexrgbscale;
m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
R_Mesh_TextureState(&m);
- RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
+ RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
break;
case TEXTURELAYERTYPE_FOG:
memset(&m, 0, sizeof(m));
m.tex[0] = R_GetTexture(r_texture_white);
m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
R_Mesh_TextureState(&m);
- RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, rsurface_lightmode, false, false);
+ if (rsurface_lightmode == 2)
+ RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
+ else if (rsurface_uselightmaptexture)
+ RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
+ else
+ RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
GL_LockArrays(0, 0);
// then apply the texture to it
GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
m.texmatrix[0] = layer->texmatrix;
m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
R_Mesh_TextureState(&m);
- RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], 0, layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
+ RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
}
else
{
m.texmatrix[0] = layer->texmatrix;
m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
R_Mesh_TextureState(&m);
- RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], rsurface_lightmode == 2 ? 2 : 1, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
+ if (rsurface_lightmode == 2)
+ RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
+ else
+ RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
}
break;
case TEXTURELAYERTYPE_TEXTURE:
m.texmatrix[0] = layer->texmatrix;
m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
R_Mesh_TextureState(&m);
- RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], 0, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
+ RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
break;
case TEXTURELAYERTYPE_FOG:
// singletexture fogging
else if (rsurface_texture->currentnumlayers)
{
GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
- GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
+ GL_CullFace((rsurface_texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
GL_LockArrays(0, 0);
}
-#define BATCHSIZE 256
static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
- int surfacelistindex;
- int batchcount;
- texture_t *t;
- msurface_t *texturesurfacelist[BATCHSIZE];
+ int i, j;
+ int texturenumsurfaces, endsurface;
+ texture_t *texture;
+ msurface_t *surface;
+ msurface_t *texturesurfacelist[1024];
+
// if the model is static it doesn't matter what value we give for
// wantnormals and wanttangents, so this logic uses only rules applicable
// to a model, knowing that they are meaningless otherwise
- if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
- RSurf_ActiveEntity(ent, false, false);
+ if (ent == r_refdef.worldentity)
+ RSurf_ActiveWorldEntity();
+ else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
+ RSurf_ActiveModelEntity(ent, false, false);
else
- RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
- batchcount = 0;
- t = NULL;
- rsurface_uselightmaptexture = false;
- for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
- {
- msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
+ RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
- if (t != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
+ for (i = 0;i < numsurfaces;i = j)
+ {
+ j = i + 1;
+ surface = rsurface_model->data_surfaces + surfacelist[i];
+ texture = surface->texture;
+ rsurface_texture = texture->currentframe;
+ rsurface_uselightmaptexture = surface->lightmaptexture != NULL;
+ // scan ahead until we find a different texture
+ endsurface = min(i + 1024, numsurfaces);
+ texturenumsurfaces = 0;
+ texturesurfacelist[texturenumsurfaces++] = surface;
+ for (;j < endsurface;j++)
{
- if (batchcount > 0)
- if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
- R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
- batchcount = 0;
- t = surface->texture;
- rsurface_uselightmaptexture = (surface->lightmaptexture != NULL);
- R_UpdateTextureInfo(ent, t);
- rsurface_texture = t->currentframe;
+ surface = rsurface_model->data_surfaces + surfacelist[j];
+ if (texture != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
+ break;
+ texturesurfacelist[texturenumsurfaces++] = surface;
}
-
- texturesurfacelist[batchcount++] = surface;
+ // render the range of surfaces
+ R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
}
- if (batchcount > 0)
- if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
- R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
+
RSurf_CleanUp();
}
-void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
+void R_QueueSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask)
{
- int texturesurfaceindex;
+ int i, j;
vec3_t tempcenter, center;
- if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
+ texture_t *texture;
+ // break the surface list down into batches by texture and use of lightmapping
+ for (i = 0;i < numsurfaces;i = j)
{
- // drawing sky transparently would be too difficult
- if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
+ j = i + 1;
+ // texture is the base texture pointer, rsurface_texture is the
+ // current frame/skin the texture is directing us to use (for example
+ // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
+ // use skin 1 instead)
+ texture = surfacelist[i]->texture;
+ rsurface_texture = texture->currentframe;
+ rsurface_uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
+ if (!(rsurface_texture->currentmaterialflags & flagsmask))
{
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ // if this texture is not the kind we want, skip ahead to the next one
+ for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
+ ;
+ continue;
+ }
+ if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
+ {
+ // transparent surfaces get pushed off into the transparent queue
+ const msurface_t *surface = surfacelist[i];
+ tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
+ tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
+ tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
+ Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
+ R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, rsurface_entity, surface - rsurface_model->data_surfaces, r_shadow_rtlight);
+ }
+ else
+ {
+ // simply scan ahead until we find a different texture or lightmap state
+ for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface_uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
+ ;
+ // render the range of surfaces
+ R_DrawTextureSurfaceList(j - i, surfacelist + i);
+ }
+ }
+}
+
+float locboxvertex3f[6*4*3] =
+{
+ 1,0,1, 1,0,0, 1,1,0, 1,1,1,
+ 0,1,1, 0,1,0, 0,0,0, 0,0,1,
+ 1,1,1, 1,1,0, 0,1,0, 0,1,1,
+ 0,0,1, 0,0,0, 1,0,0, 1,0,1,
+ 0,0,1, 1,0,1, 1,1,1, 0,1,1,
+ 1,0,0, 0,0,0, 0,1,0, 1,1,0
+};
+
+int locboxelement3i[6*2*3] =
+{
+ 0, 1, 2, 0, 2, 3,
+ 4, 5, 6, 4, 6, 7,
+ 8, 9,10, 8,10,11,
+ 12,13,14, 12,14,15,
+ 16,17,18, 16,18,19,
+ 20,21,22, 20,22,23
+};
+
+void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
+{
+ int i, j;
+ cl_locnode_t *loc = (cl_locnode_t *)ent;
+ vec3_t mins, size;
+ float vertex3f[6*4*3];
+ CHECKGLERROR
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GL_DepthMask(false);
+ GL_DepthTest(true);
+ GL_CullFace(GL_NONE);
+ R_Mesh_Matrix(&identitymatrix);
+
+ R_Mesh_VertexPointer(vertex3f);
+ R_Mesh_ColorPointer(NULL);
+ R_Mesh_ResetTextureState();
+
+ i = surfacelist[0];
+ GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
+ ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
+ ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
+ surfacelist[0] < 0 ? 0.5f : 0.125f);
+
+ if (VectorCompare(loc->mins, loc->maxs))
+ {
+ VectorSet(size, 2, 2, 2);
+ VectorMA(loc->mins, -0.5f, size, mins);
+ }
+ else
+ {
+ VectorCopy(loc->mins, mins);
+ VectorSubtract(loc->maxs, loc->mins, size);
+ }
+
+ for (i = 0;i < 6*4*3;)
+ for (j = 0;j < 3;j++, i++)
+ vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
+
+ R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i);
+}
+
+void R_DrawLocs(void)
+{
+ int index;
+ cl_locnode_t *loc, *nearestloc;
+ vec3_t center;
+ nearestloc = CL_Locs_FindNearest(cl.movement_origin);
+ for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
+ {
+ VectorLerp(loc->mins, 0.5f, loc->maxs, center);
+ R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
+ }
+}
+
+void R_DrawCollisionBrushes(entity_render_t *ent)
+{
+ int i;
+ q3mbrush_t *brush;
+ msurface_t *surface;
+ model_t *model = ent->model;
+ if (!model->brush.num_brushes)
+ return;
+ CHECKGLERROR
+ R_Mesh_ColorPointer(NULL);
+ R_Mesh_ResetTextureState();
+ GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
+ GL_DepthMask(false);
+ GL_DepthTest(!r_showdisabledepthtest.integer);
+ qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
+ for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
+ if (brush->colbrushf && brush->colbrushf->numtriangles)
+ R_DrawCollisionBrush(brush->colbrushf);
+ for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
+ if (surface->num_collisiontriangles)
+ R_DrawCollisionSurface(ent, surface);
+ qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+}
+
+void R_DrawTrianglesAndNormals(entity_render_t *ent, qboolean drawtris, qboolean drawnormals, int flagsmask)
+{
+ int i, j, k, l;
+ const int *elements;
+ msurface_t *surface;
+ model_t *model = ent->model;
+ vec3_t v;
+ CHECKGLERROR
+ GL_DepthTest(!r_showdisabledepthtest.integer);
+ GL_DepthMask(true);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ R_Mesh_ColorPointer(NULL);
+ R_Mesh_ResetTextureState();
+ for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
+ {
+ if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
+ continue;
+ rsurface_texture = surface->texture->currentframe;
+ if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
+ {
+ RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
+ if (drawtris)
{
- const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
- tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
- tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
- tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
- Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
- R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, rsurface_entity, surface - rsurface_model->data_surfaces, r_shadow_rtlight);
+ if (!rsurface_texture->currentlayers->depthmask)
+ GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
+ else if (ent == r_refdef.worldentity)
+ GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
+ else
+ GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
+ elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
+ CHECKGLERROR
+ qglBegin(GL_LINES);
+ for (k = 0;k < surface->num_triangles;k++, elements += 3)
+ {
+ qglArrayElement(elements[0]);qglArrayElement(elements[1]);
+ qglArrayElement(elements[1]);qglArrayElement(elements[2]);
+ qglArrayElement(elements[2]);qglArrayElement(elements[0]);
+ }
+ qglEnd();
+ CHECKGLERROR
+ }
+ if (drawnormals)
+ {
+ GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
+ qglBegin(GL_LINES);
+ for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
+ {
+ VectorCopy(rsurface_vertex3f + l * 3, v);
+ qglVertex3f(v[0], v[1], v[2]);
+ VectorMA(v, 8, rsurface_svector3f + l * 3, v);
+ qglVertex3f(v[0], v[1], v[2]);
+ }
+ qglEnd();
+ CHECKGLERROR
+ GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
+ qglBegin(GL_LINES);
+ for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
+ {
+ VectorCopy(rsurface_vertex3f + l * 3, v);
+ qglVertex3f(v[0], v[1], v[2]);
+ VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
+ qglVertex3f(v[0], v[1], v[2]);
+ }
+ qglEnd();
+ CHECKGLERROR
+ GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
+ qglBegin(GL_LINES);
+ for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
+ {
+ VectorCopy(rsurface_vertex3f + l * 3, v);
+ qglVertex3f(v[0], v[1], v[2]);
+ VectorMA(v, 8, rsurface_normal3f + l * 3, v);
+ qglVertex3f(v[0], v[1], v[2]);
+ }
+ qglEnd();
+ CHECKGLERROR
}
}
}
- else
- R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
+ rsurface_texture = NULL;
}
extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
-void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
+void R_DrawWorldSurfaces(qboolean skysurfaces)
{
- int i, j, k, l, endj, f, flagsmask;
+ int i, j, endj, f, flagsmask;
int counttriangles = 0;
- msurface_t *surface, *endsurface, **surfacechain;
+ msurface_t *surface, **surfacechain;
texture_t *t;
- q3mbrush_t *brush;
- model_t *model = ent->model;
- const int *elements;
+ model_t *model = r_refdef.worldmodel;
const int maxsurfacelist = 1024;
int numsurfacelist = 0;
msurface_t *surfacelist[1024];
- vec3_t v;
if (model == NULL)
return;
- // if the model is static it doesn't matter what value we give for
- // wantnormals and wanttangents, so this logic uses only rules applicable
- // to a model, knowing that they are meaningless otherwise
- if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
- RSurf_ActiveEntity(ent, false, false);
- else
- RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
+ RSurf_ActiveWorldEntity();
// update light styles
if (!skysurfaces && model->brushq1.light_styleupdatechains)
}
}
- R_UpdateAllTextureInfo(ent);
+ R_UpdateAllTextureInfo(r_refdef.worldentity);
flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
f = 0;
t = NULL;
rsurface_uselightmaptexture = false;
rsurface_texture = NULL;
numsurfacelist = 0;
- if (ent == r_refdef.worldentity)
+ j = model->firstmodelsurface;
+ endj = j + model->nummodelsurfaces;
+ while (j < endj)
{
- j = model->firstmodelsurface;
- endj = j + model->nummodelsurfaces;
- while (j < endj)
+ // quickly skip over non-visible surfaces
+ for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
+ ;
+ // quickly iterate over visible surfaces
+ for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
{
- // quickly skip over non-visible surfaces
- for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
- ;
- // quickly iterate over visible surfaces
- for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
- {
- // process this surface
- surface = model->data_surfaces + j;
- // if texture or lightmap has changed, start a new batch
- if (t != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
- {
- if (numsurfacelist)
- {
- R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
- numsurfacelist = 0;
- }
- t = surface->texture;
- rsurface_uselightmaptexture = surface->lightmaptexture != NULL;
- rsurface_texture = t->currentframe;
- f = rsurface_texture->currentmaterialflags & flagsmask;
- }
- // if this surface fits the criteria, add it to the list
- if (f && surface->num_triangles)
- {
- // if lightmap parameters changed, rebuild lightmap texture
- if (surface->cached_dlight)
- R_BuildLightMap(ent, surface);
- // add face to draw list
- surfacelist[numsurfacelist++] = surface;
- counttriangles += surface->num_triangles;
- if (numsurfacelist >= maxsurfacelist)
- {
- R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
- numsurfacelist = 0;
- }
- }
- }
- }
- }
- else
- {
- surface = model->data_surfaces + model->firstmodelsurface;
- endsurface = surface + model->nummodelsurfaces;
- for (;surface < endsurface;surface++)
- {
- // if texture or lightmap has changed, start a new batch
- if (t != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
- {
- if (numsurfacelist)
- {
- R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
- numsurfacelist = 0;
- }
- t = surface->texture;
- rsurface_uselightmaptexture = (surface->lightmaptexture != NULL);
- rsurface_texture = t->currentframe;
- f = rsurface_texture->currentmaterialflags & flagsmask;
- }
+ // process this surface
+ surface = model->data_surfaces + j;
// if this surface fits the criteria, add it to the list
- if (f && surface->num_triangles)
+ if (surface->num_triangles)
{
// if lightmap parameters changed, rebuild lightmap texture
if (surface->cached_dlight)
- R_BuildLightMap(ent, surface);
+ R_BuildLightMap(r_refdef.worldentity, surface);
// add face to draw list
surfacelist[numsurfacelist++] = surface;
counttriangles += surface->num_triangles;
if (numsurfacelist >= maxsurfacelist)
{
- R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
+ R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
numsurfacelist = 0;
}
}
}
}
if (numsurfacelist)
- R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
+ R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
r_refdef.stats.entities_triangles += counttriangles;
RSurf_CleanUp();
- if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
+ if (r_showcollisionbrushes.integer && !skysurfaces)
+ R_DrawCollisionBrushes(r_refdef.worldentity);
+
+ if (r_showtris.integer || r_shownormals.integer)
+ R_DrawTrianglesAndNormals(r_refdef.worldentity, r_showtris.integer, r_shownormals.integer, flagsmask);
+}
+
+void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces)
+{
+ int i, f, flagsmask;
+ int counttriangles = 0;
+ msurface_t *surface, *endsurface, **surfacechain;
+ texture_t *t;
+ model_t *model = ent->model;
+ const int maxsurfacelist = 1024;
+ int numsurfacelist = 0;
+ msurface_t *surfacelist[1024];
+ if (model == NULL)
+ return;
+
+ // if the model is static it doesn't matter what value we give for
+ // wantnormals and wanttangents, so this logic uses only rules applicable
+ // to a model, knowing that they are meaningless otherwise
+ if (ent == r_refdef.worldentity)
+ RSurf_ActiveWorldEntity();
+ else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
+ RSurf_ActiveModelEntity(ent, false, false);
+ else
+ RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
+
+ // update light styles
+ if (!skysurfaces && model->brushq1.light_styleupdatechains)
{
- CHECKGLERROR
- R_Mesh_Matrix(&ent->matrix);
- R_Mesh_ColorPointer(NULL);
- R_Mesh_ResetTextureState();
- GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
- GL_DepthMask(false);
- GL_DepthTest(!r_showdisabledepthtest.integer);
- qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
- for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
- if (brush->colbrushf && brush->colbrushf->numtriangles)
- R_DrawCollisionBrush(brush->colbrushf);
- for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
- if (surface->num_collisiontriangles)
- R_DrawCollisionSurface(ent, surface);
- qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+ for (i = 0;i < model->brushq1.light_styles;i++)
+ {
+ if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
+ {
+ model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
+ if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
+ for (;(surface = *surfacechain);surfacechain++)
+ surface->cached_dlight = true;
+ }
+ }
}
- if (r_showtris.integer || r_shownormals.integer)
+ R_UpdateAllTextureInfo(ent);
+ flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
+ f = 0;
+ t = NULL;
+ rsurface_uselightmaptexture = false;
+ rsurface_texture = NULL;
+ numsurfacelist = 0;
+ surface = model->data_surfaces + model->firstmodelsurface;
+ endsurface = surface + model->nummodelsurfaces;
+ for (;surface < endsurface;surface++)
{
- CHECKGLERROR
- GL_DepthTest(!r_showdisabledepthtest.integer);
- GL_DepthMask(true);
- GL_BlendFunc(GL_ONE, GL_ZERO);
- R_Mesh_ColorPointer(NULL);
- R_Mesh_ResetTextureState();
- for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
+ // if this surface fits the criteria, add it to the list
+ if (surface->num_triangles)
{
- if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
- continue;
- rsurface_texture = surface->texture->currentframe;
- if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
+ // if lightmap parameters changed, rebuild lightmap texture
+ if (surface->cached_dlight)
+ R_BuildLightMap(ent, surface);
+ // add face to draw list
+ surfacelist[numsurfacelist++] = surface;
+ counttriangles += surface->num_triangles;
+ if (numsurfacelist >= maxsurfacelist)
{
- RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
- if (r_showtris.integer)
- {
- if (!rsurface_texture->currentlayers->depthmask)
- GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
- else if (ent == r_refdef.worldentity)
- GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
- else
- GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
- elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
- CHECKGLERROR
- qglBegin(GL_LINES);
- for (k = 0;k < surface->num_triangles;k++, elements += 3)
- {
- qglArrayElement(elements[0]);qglArrayElement(elements[1]);
- qglArrayElement(elements[1]);qglArrayElement(elements[2]);
- qglArrayElement(elements[2]);qglArrayElement(elements[0]);
- }
- qglEnd();
- CHECKGLERROR
- }
- if (r_shownormals.integer)
- {
- GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
- qglBegin(GL_LINES);
- for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
- {
- VectorCopy(rsurface_vertex3f + l * 3, v);
- qglVertex3f(v[0], v[1], v[2]);
- VectorMA(v, 8, rsurface_svector3f + l * 3, v);
- qglVertex3f(v[0], v[1], v[2]);
- }
- qglEnd();
- CHECKGLERROR
- GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
- qglBegin(GL_LINES);
- for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
- {
- VectorCopy(rsurface_vertex3f + l * 3, v);
- qglVertex3f(v[0], v[1], v[2]);
- VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
- qglVertex3f(v[0], v[1], v[2]);
- }
- qglEnd();
- CHECKGLERROR
- GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
- qglBegin(GL_LINES);
- for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
- {
- VectorCopy(rsurface_vertex3f + l * 3, v);
- qglVertex3f(v[0], v[1], v[2]);
- VectorMA(v, 8, rsurface_normal3f + l * 3, v);
- qglVertex3f(v[0], v[1], v[2]);
- }
- qglEnd();
- CHECKGLERROR
- }
+ R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
+ numsurfacelist = 0;
}
}
- rsurface_texture = NULL;
}
+ if (numsurfacelist)
+ R_QueueSurfaceList(numsurfacelist, surfacelist, flagsmask);
+ r_refdef.stats.entities_triangles += counttriangles;
+ RSurf_CleanUp();
+
+ if (r_showcollisionbrushes.integer && !skysurfaces)
+ R_DrawCollisionBrushes(ent);
+
+ if (r_showtris.integer || r_shownormals.integer)
+ R_DrawTrianglesAndNormals(ent, r_showtris.integer, r_shownormals.integer, flagsmask);
}