2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // r_surf.c: surface-related refresh code
24 #define MAX_LIGHTMAP_SIZE 256
26 static unsigned int intblocklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*3]; // LordHavoc: *3 for colored lighting
27 static float floatblocklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*3]; // LordHavoc: *3 for colored lighting
29 static qbyte templight[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*4];
31 cvar_t r_ambient = {0, "r_ambient", "0"};
32 cvar_t r_vertexsurfaces = {0, "r_vertexsurfaces", "0"};
33 cvar_t r_dlightmap = {CVAR_SAVE, "r_dlightmap", "1"};
34 cvar_t r_drawportals = {0, "r_drawportals", "0"};
35 cvar_t r_testvis = {0, "r_testvis", "0"};
36 cvar_t r_floatbuildlightmap = {0, "r_floatbuildlightmap", "0"};
37 cvar_t r_detailtextures = {CVAR_SAVE, "r_detailtextures", "1"};
38 cvar_t r_surfaceworldnode = {0, "r_surfaceworldnode", "0"};
39 cvar_t r_cullsurface = {0, "r_cullsurface", "0"};
41 static int dlightdivtable[32768];
43 // variables used by R_PVSUpdate
44 int r_pvsframecount = 0;
45 mleaf_t *r_viewleaf = NULL;
46 int r_viewleafnovis = 0;
48 static int R_IntAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surf)
50 int sdtable[256], lnum, td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, smax3, red, green, blue, lit, dist2, impacts, impactt, subtract;
52 float dist, impact[3], local[3];
54 // LordHavoc: use 64bit integer... shame it's not very standardized...
55 #if _MSC_VER || __BORLANDC__
63 smax = (surf->extents[0] >> 4) + 1;
64 tmax = (surf->extents[1] >> 4) + 1;
67 for (lnum = 0; lnum < r_numdlights; lnum++)
69 if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31))))
70 continue; // not lit by this light
72 Matrix4x4_Transform(matrix, r_dlight[lnum].origin, local);
73 dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
75 // for comparisons to minimum acceptable light
76 // compensate for LIGHTOFFSET
77 maxdist = (int) r_dlight[lnum].cullradius2 + LIGHTOFFSET;
84 if (surf->plane->type < 3)
86 VectorCopy(local, impact);
87 impact[surf->plane->type] -= dist;
91 impact[0] = local[0] - surf->plane->normal[0] * dist;
92 impact[1] = local[1] - surf->plane->normal[1] * dist;
93 impact[2] = local[2] - surf->plane->normal[2] * dist;
96 impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
97 impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
99 s = bound(0, impacts, smax * 16) - impacts;
100 t = bound(0, impactt, tmax * 16) - impactt;
101 i = s * s + t * t + dist2;
105 // reduce calculations
106 for (s = 0, i = impacts; s < smax; s++, i -= 16)
107 sdtable[s] = i * i + dist2;
109 maxdist3 = maxdist - dist2;
111 // convert to 8.8 blocklights format
112 red = r_dlight[lnum].light[0];
113 green = r_dlight[lnum].light[1];
114 blue = r_dlight[lnum].light[2];
115 subtract = (int) (r_dlight[lnum].subtract * 4194304.0f);
119 for (t = 0;t < tmax;t++, i -= 16)
122 // make sure some part of it is visible on this line
125 maxdist2 = maxdist - td;
126 for (s = 0;s < smax;s++)
128 if (sdtable[s] < maxdist2)
130 k = dlightdivtable[(sdtable[s] + td) >> 7] - subtract;
133 bl[0] += (red * k) >> 7;
134 bl[1] += (green * k) >> 7;
135 bl[2] += (blue * k) >> 7;
149 static int R_FloatAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surf)
151 int lnum, s, t, smax, tmax, smax3, lit, impacts, impactt;
152 float sdtable[256], *bl, k, dist, dist2, maxdist, maxdist2, maxdist3, td1, td, red, green, blue, impact[3], local[3], subtract;
156 smax = (surf->extents[0] >> 4) + 1;
157 tmax = (surf->extents[1] >> 4) + 1;
160 for (lnum = 0; lnum < r_numdlights; lnum++)
162 if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31))))
163 continue; // not lit by this light
165 Matrix4x4_Transform(matrix, r_dlight[lnum].origin, local);
166 dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
168 // for comparisons to minimum acceptable light
169 // compensate for LIGHTOFFSET
170 maxdist = (int) r_dlight[lnum].cullradius2 + LIGHTOFFSET;
173 dist2 += LIGHTOFFSET;
174 if (dist2 >= maxdist)
177 if (surf->plane->type < 3)
179 VectorCopy(local, impact);
180 impact[surf->plane->type] -= dist;
184 impact[0] = local[0] - surf->plane->normal[0] * dist;
185 impact[1] = local[1] - surf->plane->normal[1] * dist;
186 impact[2] = local[2] - surf->plane->normal[2] * dist;
189 impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
190 impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
192 td = bound(0, impacts, smax * 16) - impacts;
193 td1 = bound(0, impactt, tmax * 16) - impactt;
194 td = td * td + td1 * td1 + dist2;
198 // reduce calculations
199 for (s = 0, td1 = impacts; s < smax; s++, td1 -= 16.0f)
200 sdtable[s] = td1 * td1 + dist2;
202 maxdist3 = maxdist - dist2;
204 // convert to 8.8 blocklights format
205 red = r_dlight[lnum].light[0];
206 green = r_dlight[lnum].light[1];
207 blue = r_dlight[lnum].light[2];
208 subtract = r_dlight[lnum].subtract * 32768.0f;
209 bl = floatblocklights;
212 for (t = 0;t < tmax;t++, td1 -= 16.0f)
215 // make sure some part of it is visible on this line
218 maxdist2 = maxdist - td;
219 for (s = 0;s < smax;s++)
221 if (sdtable[s] < maxdist2)
223 k = (32768.0f / (sdtable[s] + td)) - subtract;
243 Combine and scale multiple lightmaps into the 8.8 format in blocklights
246 static void R_BuildLightMap (const entity_render_t *ent, msurface_t *surf, int dlightchanged)
248 if (!r_floatbuildlightmap.integer)
250 int smax, tmax, i, j, size, size3, shift, maps, stride, l;
251 unsigned int *bl, scale;
252 qbyte *lightmap, *out, *stain;
254 // update cached lighting info
255 surf->cached_dlight = 0;
256 surf->cached_lightscalebit = lightscalebit;
257 surf->cached_ambient = r_ambient.value;
258 surf->cached_light[0] = d_lightstylevalue[surf->styles[0]];
259 surf->cached_light[1] = d_lightstylevalue[surf->styles[1]];
260 surf->cached_light[2] = d_lightstylevalue[surf->styles[2]];
261 surf->cached_light[3] = d_lightstylevalue[surf->styles[3]];
263 smax = (surf->extents[0]>>4)+1;
264 tmax = (surf->extents[1]>>4)+1;
267 lightmap = surf->samples;
269 // set to full bright if no light data
271 if ((ent->effects & EF_FULLBRIGHT) || !ent->model->lightdata)
273 for (i = 0;i < size3;i++)
279 j = r_ambient.value * 512.0f; // would be 128.0f logically, but using 512.0f to match winquake style
282 for (i = 0;i < size3;i++)
286 memset(bl, 0, size*3*sizeof(unsigned int));
288 if (surf->dlightframe == r_framecount && r_dlightmap.integer)
290 surf->cached_dlight = R_IntAddDynamicLights(&ent->inversematrix, surf);
291 if (surf->cached_dlight)
293 else if (dlightchanged)
294 return; // don't upload if only updating dlights and none mattered
297 // add all the lightmaps
301 for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++, lightmap += size3)
302 for (scale = d_lightstylevalue[surf->styles[maps]], i = 0;i < size3;i++)
303 bl[i] += lightmap[i] * scale;
307 stain = surf->stainsamples;
310 // deal with lightmap brightness scale
311 shift = 7 + lightscalebit + 8;
312 if (ent->model->lightmaprgba)
314 stride = (surf->lightmaptexturestride - smax) * 4;
315 for (i = 0;i < tmax;i++, out += stride)
317 for (j = 0;j < smax;j++)
319 l = (*bl++ * *stain++) >> shift;*out++ = min(l, 255);
320 l = (*bl++ * *stain++) >> shift;*out++ = min(l, 255);
321 l = (*bl++ * *stain++) >> shift;*out++ = min(l, 255);
328 stride = (surf->lightmaptexturestride - smax) * 3;
329 for (i = 0;i < tmax;i++, out += stride)
331 for (j = 0;j < smax;j++)
333 l = (*bl++ * *stain++) >> shift;*out++ = min(l, 255);
334 l = (*bl++ * *stain++) >> shift;*out++ = min(l, 255);
335 l = (*bl++ * *stain++) >> shift;*out++ = min(l, 255);
340 R_UpdateTexture(surf->lightmaptexture, templight);
344 int smax, tmax, i, j, size, size3, maps, stride, l;
346 qbyte *lightmap, *out, *stain;
348 // update cached lighting info
349 surf->cached_dlight = 0;
350 surf->cached_lightscalebit = lightscalebit;
351 surf->cached_ambient = r_ambient.value;
352 surf->cached_light[0] = d_lightstylevalue[surf->styles[0]];
353 surf->cached_light[1] = d_lightstylevalue[surf->styles[1]];
354 surf->cached_light[2] = d_lightstylevalue[surf->styles[2]];
355 surf->cached_light[3] = d_lightstylevalue[surf->styles[3]];
357 smax = (surf->extents[0]>>4)+1;
358 tmax = (surf->extents[1]>>4)+1;
361 lightmap = surf->samples;
363 // set to full bright if no light data
364 bl = floatblocklights;
365 if ((ent->effects & EF_FULLBRIGHT) || !ent->model->lightdata)
368 j = r_ambient.value * 512.0f; // would be 128.0f logically, but using 512.0f to match winquake style
373 for (i = 0;i < size3;i++)
377 memset(bl, 0, size*3*sizeof(float));
379 if (surf->dlightframe == r_framecount && r_dlightmap.integer)
381 surf->cached_dlight = R_FloatAddDynamicLights(&ent->inversematrix, surf);
382 if (surf->cached_dlight)
384 else if (dlightchanged)
385 return; // don't upload if only updating dlights and none mattered
388 // add all the lightmaps
391 bl = floatblocklights;
392 for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++, lightmap += size3)
393 for (scale = d_lightstylevalue[surf->styles[maps]], i = 0;i < size3;i++)
394 bl[i] += lightmap[i] * scale;
397 stain = surf->stainsamples;
398 bl = floatblocklights;
400 // deal with lightmap brightness scale
401 scale = 1.0f / (1 << (7 + lightscalebit + 8));
402 if (ent->model->lightmaprgba)
404 stride = (surf->lightmaptexturestride - smax) * 4;
405 for (i = 0;i < tmax;i++, out += stride)
407 for (j = 0;j < smax;j++)
409 l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
410 l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
411 l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
418 stride = (surf->lightmaptexturestride - smax) * 3;
419 for (i = 0;i < tmax;i++, out += stride)
421 for (j = 0;j < smax;j++)
423 l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
424 l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
425 l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
430 R_UpdateTexture(surf->lightmaptexture, templight);
434 void R_StainNode (mnode_t *node, model_t *model, vec3_t origin, float radius, int icolor[8])
437 msurface_t *surf, *endsurf;
438 int sdtable[256], td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, smax3, dist2, impacts, impactt, subtract, a, stained, cr, cg, cb, ca, ratio;
441 // LordHavoc: use 64bit integer... shame it's not very standardized...
442 #if _MSC_VER || __BORLANDC__
449 // for comparisons to minimum acceptable light
450 // compensate for 256 offset
451 maxdist = radius * radius + 256.0f;
453 // clamp radius to avoid exceeding 32768 entry division table
454 if (maxdist > 4194304)
457 subtract = (int) ((1.0f / maxdist) * 4194304.0f);
460 if (node->contents < 0)
462 ndist = PlaneDiff(origin, node->plane);
465 node = node->children[0];
470 node = node->children[1];
474 dist2 = ndist * ndist + 256.0f;
477 maxdist3 = maxdist - dist2;
479 if (node->plane->type < 3)
481 VectorCopy(origin, impact);
482 impact[node->plane->type] -= ndist;
486 impact[0] = origin[0] - node->plane->normal[0] * ndist;
487 impact[1] = origin[1] - node->plane->normal[1] * ndist;
488 impact[2] = origin[2] - node->plane->normal[2] * ndist;
491 for (surf = model->surfaces + node->firstsurface, endsurf = surf + node->numsurfaces;surf < endsurf;surf++)
493 if (surf->stainsamples)
495 smax = (surf->extents[0] >> 4) + 1;
496 tmax = (surf->extents[1] >> 4) + 1;
498 impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
499 impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
501 s = bound(0, impacts, smax * 16) - impacts;
502 t = bound(0, impactt, tmax * 16) - impactt;
503 i = s * s + t * t + dist2;
507 // reduce calculations
508 for (s = 0, i = impacts; s < smax; s++, i -= 16)
509 sdtable[s] = i * i + dist2;
511 // convert to 8.8 blocklights format
512 bl = surf->stainsamples;
517 for (t = 0;t < tmax;t++, i -= 16)
520 // make sure some part of it is visible on this line
523 maxdist2 = maxdist - td;
524 for (s = 0;s < smax;s++)
526 if (sdtable[s] < maxdist2)
528 k = dlightdivtable[(sdtable[s] + td) >> 7] - subtract;
531 ratio = rand() & 255;
532 ca = (((icolor[7] - icolor[3]) * ratio) >> 8) + icolor[3];
536 a = bound(0, a, 256);
537 cr = (((icolor[4] - icolor[0]) * ratio) >> 8) + icolor[0];
538 cg = (((icolor[5] - icolor[1]) * ratio) >> 8) + icolor[1];
539 cb = (((icolor[6] - icolor[2]) * ratio) >> 8) + icolor[2];
540 bl[0] = (qbyte) ((((cr - (int) bl[0]) * a) >> 8) + (int) bl[0]);
541 bl[1] = (qbyte) ((((cg - (int) bl[1]) * a) >> 8) + (int) bl[1]);
542 bl[2] = (qbyte) ((((cb - (int) bl[2]) * a) >> 8) + (int) bl[2]);
553 // force lightmap upload
555 surf->cached_dlight = true;
560 if (node->children[0]->contents >= 0)
562 if (node->children[1]->contents >= 0)
564 R_StainNode(node->children[0], model, origin, radius, icolor);
565 node = node->children[1];
570 node = node->children[0];
574 else if (node->children[1]->contents >= 0)
576 node = node->children[1];
581 void R_Stain (vec3_t origin, float radius, int cr1, int cg1, int cb1, int ca1, int cr2, int cg2, int cb2, int ca2)
584 entity_render_t *ent;
596 model = cl.worldmodel;
598 R_StainNode(model->nodes + model->hulls[0].firstclipnode, model, origin, radius, icolor);
600 // look for embedded bmodels
601 for (n = 0;n < cl_num_brushmodel_entities;n++)
603 ent = cl_brushmodel_entities[n];
605 if (model && model->name[0] == '*')
607 Mod_CheckLoaded(model);
608 if (model->type == mod_brush)
610 Matrix4x4_Transform(&ent->inversematrix, origin, org);
611 R_StainNode(model->nodes + model->hulls[0].firstclipnode, model, org, radius, icolor);
619 =============================================================
623 =============================================================
626 static void RSurf_CopyXYZ(const surfvertex_t *in, float *out, int numverts)
629 for (i = 0;i < numverts;i++, in++, out += 4)
631 VectorCopy(in->v, out);
636 static void RSurf_CopyST(const surfvertex_t *in, float *out, int numverts)
639 for (i = 0;i < numverts;i++, in++, out += 2)
646 static void RSurf_CopyUV(const surfvertex_t *in, float *out, int numverts)
649 for (i = 0;i < numverts;i++, in++, out += 2)
656 static void RSurf_CopyAB(const surfvertex_t *in, float *out, int numverts)
659 for (i = 0;i < numverts;i++, in++, out += 2)
666 static void RSurf_AddLightmapToVertexColors(const surfvertex_t *in, float *c, int numverts, const qbyte *samples, int size3, const qbyte *styles)
671 if (styles[0] != 255)
673 for (i = 0;i < numverts;i++, in++, c += 4)
675 lm = samples + in->lightmapoffset;
676 scale = d_lightstylevalue[styles[0]] * (1.0f / 32768.0f);
677 VectorMA(c, scale, lm, c);
678 if (styles[1] != 255)
681 scale = d_lightstylevalue[styles[1]] * (1.0f / 32768.0f);
682 VectorMA(c, scale, lm, c);
683 if (styles[2] != 255)
686 scale = d_lightstylevalue[styles[2]] * (1.0f / 32768.0f);
687 VectorMA(c, scale, lm, c);
688 if (styles[3] != 255)
691 scale = d_lightstylevalue[styles[3]] * (1.0f / 32768.0f);
692 VectorMA(c, scale, lm, c);
700 static void RSurf_FogColors(const float *v, float *c, float colorscale, int numverts, const float *modelorg)
706 for (i = 0;i < numverts;i++, v += 4, c += 4)
708 VectorSubtract(v, modelorg, diff);
709 f = colorscale * (1 - exp(fogdensity/DotProduct(diff, diff)));
710 VectorScale(c, f, c);
713 else if (colorscale != 1)
714 for (i = 0;i < numverts;i++, c += 4)
715 VectorScale(c, colorscale, c);
718 static void RSurf_FoggedColors(const float *v, float *c, float r, float g, float b, float a, float colorscale, int numverts, const float *modelorg)
727 for (i = 0;i < numverts;i++, v += 4, c += 4)
729 VectorSubtract(v, modelorg, diff);
730 f = 1 - exp(fogdensity/DotProduct(diff, diff));
739 for (i = 0;i < numverts;i++, c += 4)
749 static void RSurf_FogPassColors(const float *v, float *c, float r, float g, float b, float a, float colorscale, int numverts, const float *modelorg)
756 for (i = 0;i < numverts;i++, v += 4, c += 4)
758 VectorSubtract(v, modelorg, diff);
759 f = exp(fogdensity/DotProduct(diff, diff));
767 static void RSurf_ScaleColors(float *c, float scale, int numverts)
771 for (i = 0;i < numverts;i++, c += 4)
772 VectorScale(c, scale, c);
775 static int RSurf_LightSeparate(const matrix4x4_t *matrix, const int *dlightbits, int numverts, const float *vert, float *color)
780 int i, l, lit = false;
783 for (l = 0;l < r_numdlights;l++)
785 if (dlightbits[l >> 5] & (1 << (l & 31)))
788 Matrix4x4_Transform(matrix, rd->origin, lightorigin);
789 for (i = 0, v = vert, c = color;i < numverts;i++, v += 4, c += 4)
791 f = VectorDistance2(v, lightorigin) + LIGHTOFFSET;
792 if (f < rd->cullradius2)
794 f = (1.0f / f) - rd->subtract;
795 VectorMA(c, f, rd->light, c);
804 // note: this untransforms lights to do the checking,
805 // and takes surf->mesh->vertex data
806 static int RSurf_LightCheck(const matrix4x4_t *matrix, const int *dlightbits, surfmesh_t *mesh)
812 for (l = 0;l < r_numdlights;l++)
814 if (dlightbits[l >> 5] & (1 << (l & 31)))
817 Matrix4x4_Transform(matrix, rd->origin, lightorigin);
818 for (i = 0, sv = mesh->vertex;i < mesh->numverts;i++, sv++)
819 if (VectorDistance2(sv->v, lightorigin) < rd->cullradius2)
826 static void RSurfShader_Sky(const entity_render_t *ent, const msurface_t *firstsurf)
828 const msurface_t *surf;
832 // LordHavoc: HalfLife maps have freaky skypolys...
833 if (ent->model->ishlbsp)
838 skyrendernow = false;
843 // draw depth-only polys
844 memset(&m, 0, sizeof(m));
847 m.blendfunc1 = GL_ZERO;
848 m.blendfunc2 = GL_ONE;
853 m.blendfunc1 = GL_ONE;
854 m.blendfunc2 = GL_ZERO;
857 m.matrix = ent->matrix;
858 for (surf = firstsurf;surf;surf = surf->chain)
860 for (mesh = surf->mesh;mesh;mesh = mesh->chain)
862 m.numtriangles = mesh->numtriangles;
863 m.numverts = mesh->numverts;
864 if (R_Mesh_Draw_GetBuffer(&m, false))
866 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
867 RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
869 memset(m.color, 0, m.numverts * sizeof(float[4]));
871 R_FillColors(m.color, m.numverts, fogcolor[0] * m.colorscale, fogcolor[1] * m.colorscale, fogcolor[2] * m.colorscale, 1);
878 static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
880 const entity_render_t *ent = calldata1;
881 msurface_t *surf = ent->model->surfaces + calldata2;
885 float alpha = ent->alpha * (surf->flags & SURF_DRAWNOALPHA ? 1 : r_wateralpha.value);
887 Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
889 memset(&m, 0, sizeof(m));
890 if (ent->effects & EF_ADDITIVE)
892 m.blendfunc1 = GL_SRC_ALPHA;
893 m.blendfunc2 = GL_ONE;
895 else if (surf->currenttexture->fogtexture != NULL || alpha < 1)
897 m.blendfunc1 = GL_SRC_ALPHA;
898 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
902 m.blendfunc1 = GL_ONE;
903 m.blendfunc2 = GL_ZERO;
905 m.tex[0] = R_GetTexture(surf->currenttexture->texture);
906 m.matrix = ent->matrix;
907 for (mesh = surf->mesh;mesh;mesh = mesh->chain)
909 m.numtriangles = mesh->numtriangles;
910 m.numverts = mesh->numverts;
911 if (R_Mesh_Draw_GetBuffer(&m, true))
913 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
914 RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
915 RSurf_CopyST(mesh->vertex, m.texcoords[0], m.numverts);
916 f = surf->flags & SURF_DRAWFULLBRIGHT ? 1.0f : ((surf->flags & SURF_LIGHTMAP) ? 0 : 0.5f);
917 R_FillColors(m.color, m.numverts, f, f, f, alpha);
918 if (!(surf->flags & SURF_DRAWFULLBRIGHT || ent->effects & EF_FULLBRIGHT))
920 if (surf->dlightframe == r_framecount)
921 RSurf_LightSeparate(&ent->inversematrix, surf->dlightbits, m.numverts, m.vertex, m.color);
922 if (surf->flags & SURF_LIGHTMAP)
923 RSurf_AddLightmapToVertexColors(mesh->vertex, m.color, m.numverts, surf->samples, ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3, surf->styles);
925 RSurf_FogColors(m.vertex, m.color, m.colorscale, m.numverts, modelorg);
932 memset(&m, 0, sizeof(m));
933 m.blendfunc1 = GL_SRC_ALPHA;
934 m.blendfunc2 = GL_ONE;
935 m.tex[0] = R_GetTexture(surf->currenttexture->fogtexture);
936 m.matrix = ent->matrix;
937 for (mesh = surf->mesh;mesh;mesh = mesh->chain)
939 m.numtriangles = mesh->numtriangles;
940 m.numverts = mesh->numverts;
941 if (R_Mesh_Draw_GetBuffer(&m, false))
943 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
944 RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
946 RSurf_CopyST(mesh->vertex, m.texcoords[0], m.numverts);
947 RSurf_FogPassColors(m.vertex, m.color, fogcolor[0], fogcolor[1], fogcolor[2], alpha, m.colorscale, m.numverts, modelorg);
954 static void RSurfShader_Water(const entity_render_t *ent, const msurface_t *firstsurf)
956 const msurface_t *surf;
958 for (surf = firstsurf;surf;surf = surf->chain)
960 if ((r_wateralpha.value < 1 && !(surf->flags & SURF_DRAWNOALPHA)) || ent->effects & EF_ADDITIVE || surf->currenttexture->fogtexture)
962 Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
963 R_MeshQueue_AddTransparent(center, RSurfShader_Water_Callback, ent, surf - ent->model->surfaces);
966 R_MeshQueue_Add(RSurfShader_Water_Callback, ent, surf - ent->model->surfaces);
970 static void RSurfShader_Wall_Pass_BaseVertex(const entity_render_t *ent, const msurface_t *surf)
976 Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
977 memset(&m, 0, sizeof(m));
978 if (ent->effects & EF_ADDITIVE)
980 m.blendfunc1 = GL_SRC_ALPHA;
981 m.blendfunc2 = GL_ONE;
983 else if (surf->currenttexture->fogtexture != NULL || ent->alpha < 1)
985 m.blendfunc1 = GL_SRC_ALPHA;
986 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
990 m.blendfunc1 = GL_ONE;
991 m.blendfunc2 = GL_ZERO;
993 m.tex[0] = R_GetTexture(surf->currenttexture->texture);
994 base = ent->effects & EF_FULLBRIGHT ? 2.0f : r_ambient.value * (1.0f / 64.0f);
995 m.matrix = ent->matrix;
996 for (mesh = surf->mesh;mesh;mesh = mesh->chain)
998 m.numtriangles = mesh->numtriangles;
999 m.numverts = mesh->numverts;
1000 if (R_Mesh_Draw_GetBuffer(&m, true))
1002 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1003 RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
1004 RSurf_CopyST(mesh->vertex, m.texcoords[0], m.numverts);
1005 R_FillColors(m.color, m.numverts, base, base, base, ent->alpha);
1006 if (!(ent->effects & EF_FULLBRIGHT))
1008 if (surf->dlightframe == r_framecount)
1009 RSurf_LightSeparate(&ent->inversematrix, surf->dlightbits, m.numverts, m.vertex, m.color);
1010 if (surf->flags & SURF_LIGHTMAP)
1011 RSurf_AddLightmapToVertexColors(mesh->vertex, m.color, m.numverts, surf->samples, ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3, surf->styles);
1013 RSurf_FogColors(m.vertex, m.color, m.colorscale, m.numverts, modelorg);
1019 static void RSurfShader_Wall_Pass_BaseFullbright(const entity_render_t *ent, const msurface_t *surf)
1022 rmeshbufferinfo_t m;
1024 Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
1025 memset(&m, 0, sizeof(m));
1026 if (ent->effects & EF_ADDITIVE)
1028 m.blendfunc1 = GL_SRC_ALPHA;
1029 m.blendfunc2 = GL_ONE;
1031 else if (surf->currenttexture->fogtexture != NULL || ent->alpha < 1)
1033 m.blendfunc1 = GL_SRC_ALPHA;
1034 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1038 m.blendfunc1 = GL_ONE;
1039 m.blendfunc2 = GL_ZERO;
1041 m.tex[0] = R_GetTexture(surf->currenttexture->texture);
1042 m.matrix = ent->matrix;
1043 for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1045 m.numtriangles = mesh->numtriangles;
1046 m.numverts = mesh->numverts;
1047 if (R_Mesh_Draw_GetBuffer(&m, false))
1049 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1050 RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
1051 RSurf_CopyST(mesh->vertex, m.texcoords[0], m.numverts);
1052 RSurf_FoggedColors(m.vertex, m.color, 1, 1, 1, ent->alpha, m.colorscale, m.numverts, modelorg);
1058 static void RSurfShader_Wall_Pass_Glow(const entity_render_t *ent, const msurface_t *surf)
1061 rmeshbufferinfo_t m;
1063 Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
1064 memset(&m, 0, sizeof(m));
1065 m.blendfunc1 = GL_SRC_ALPHA;
1066 m.blendfunc2 = GL_ONE;
1067 m.tex[0] = R_GetTexture(surf->currenttexture->glowtexture);
1068 m.matrix = ent->matrix;
1069 for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1071 m.numtriangles = mesh->numtriangles;
1072 m.numverts = mesh->numverts;
1073 if (R_Mesh_Draw_GetBuffer(&m, false))
1075 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1076 RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
1077 RSurf_CopyST(mesh->vertex, m.texcoords[0], m.numverts);
1078 RSurf_FoggedColors(m.vertex, m.color, 1, 1, 1, ent->alpha, m.colorscale, m.numverts, modelorg);
1084 static void RSurfShader_Wall_Pass_Fog(const entity_render_t *ent, const msurface_t *surf)
1087 rmeshbufferinfo_t m;
1089 Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
1090 memset(&m, 0, sizeof(m));
1091 m.blendfunc1 = GL_SRC_ALPHA;
1092 m.blendfunc2 = GL_ONE;
1093 m.matrix = ent->matrix;
1094 m.tex[0] = R_GetTexture(surf->currenttexture->fogtexture);
1095 for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1097 m.numtriangles = mesh->numtriangles;
1098 m.numverts = mesh->numverts;
1099 if (R_Mesh_Draw_GetBuffer(&m, false))
1101 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1102 RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
1104 RSurf_CopyST(mesh->vertex, m.texcoords[0], m.numverts);
1105 RSurf_FogPassColors(m.vertex, m.color, fogcolor[0], fogcolor[1], fogcolor[2], ent->alpha, m.colorscale, m.numverts, modelorg);
1111 static void RSurfShader_OpaqueWall_Pass_TripleTexCombine(const entity_render_t *ent, const msurface_t *surf)
1114 rmeshbufferinfo_t m;
1116 memset(&m, 0, sizeof(m));
1117 m.blendfunc1 = GL_ONE;
1118 m.blendfunc2 = GL_ZERO;
1119 m.tex[0] = R_GetTexture(surf->currenttexture->texture);
1120 m.texrgbscale[0] = 1.0f;
1121 m.tex[1] = R_GetTexture(surf->lightmaptexture);
1122 m.texrgbscale[1] = 4.0f;
1123 m.tex[2] = R_GetTexture(surf->currenttexture->detailtexture);
1124 m.texrgbscale[2] = 2.0f;
1125 m.matrix = ent->matrix;
1126 for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1128 m.numtriangles = mesh->numtriangles;
1129 m.numverts = mesh->numverts;
1130 if (R_Mesh_Draw_GetBuffer(&m, false))
1132 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1133 RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
1134 cl = (float) (1 << lightscalebit) * m.colorscale;
1135 R_FillColors(m.color, m.numverts, cl, cl, cl, 1);
1136 RSurf_CopyST(mesh->vertex, m.texcoords[0], m.numverts);
1137 RSurf_CopyUV(mesh->vertex, m.texcoords[1], m.numverts);
1138 RSurf_CopyAB(mesh->vertex, m.texcoords[2], m.numverts);
1144 static void RSurfShader_OpaqueWall_Pass_BaseMTex(const entity_render_t *ent, const msurface_t *surf)
1147 rmeshbufferinfo_t m;
1149 memset(&m, 0, sizeof(m));
1150 m.blendfunc1 = GL_ONE;
1151 m.blendfunc2 = GL_ZERO;
1152 m.tex[0] = R_GetTexture(surf->currenttexture->texture);
1153 m.tex[1] = R_GetTexture(surf->lightmaptexture);
1154 m.matrix = ent->matrix;
1155 for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1157 m.numtriangles = mesh->numtriangles;
1158 m.numverts = mesh->numverts;
1159 if (R_Mesh_Draw_GetBuffer(&m, true))
1161 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1162 RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
1163 cl = (float) (1 << lightscalebit) * m.colorscale;
1164 R_FillColors(m.color, m.numverts, cl, cl, cl, 1);
1165 RSurf_CopyST(mesh->vertex, m.texcoords[0], m.numverts);
1166 RSurf_CopyUV(mesh->vertex, m.texcoords[1], m.numverts);
1172 static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent, const msurface_t *surf)
1175 rmeshbufferinfo_t m;
1177 memset(&m, 0, sizeof(m));
1178 m.blendfunc1 = GL_ONE;
1179 m.blendfunc2 = GL_ZERO;
1180 m.tex[0] = R_GetTexture(surf->currenttexture->texture);
1181 m.matrix = ent->matrix;
1182 for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1184 m.numtriangles = mesh->numtriangles;
1185 m.numverts = mesh->numverts;
1186 if (R_Mesh_Draw_GetBuffer(&m, false))
1188 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1189 RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
1191 R_FillColors(m.color, m.numverts, cl, cl, cl, 1);
1192 RSurf_CopyST(mesh->vertex, m.texcoords[0], m.numverts);
1198 static void RSurfShader_OpaqueWall_Pass_BaseLightmap(const entity_render_t *ent, const msurface_t *surf)
1201 rmeshbufferinfo_t m;
1203 memset(&m, 0, sizeof(m));
1204 m.blendfunc1 = GL_ZERO;
1205 m.blendfunc2 = GL_SRC_COLOR;
1206 m.tex[0] = R_GetTexture(surf->lightmaptexture);
1207 m.matrix = ent->matrix;
1208 for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1210 m.numtriangles = mesh->numtriangles;
1211 m.numverts = mesh->numverts;
1212 if (R_Mesh_Draw_GetBuffer(&m, true))
1214 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1215 RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
1216 cl = (float) (1 << lightscalebit) * m.colorscale;
1217 R_FillColors(m.color, m.numverts, cl, cl, cl, 1);
1218 RSurf_CopyUV(mesh->vertex, m.texcoords[0], m.numverts);
1224 static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const msurface_t *surf)
1227 rmeshbufferinfo_t m;
1229 if (surf->dlightframe != r_framecount)
1231 if (ent->effects & EF_FULLBRIGHT)
1234 memset(&m, 0, sizeof(m));
1235 m.blendfunc1 = GL_SRC_ALPHA;
1236 m.blendfunc2 = GL_ONE;
1237 m.tex[0] = R_GetTexture(surf->currenttexture->texture);
1238 m.matrix = ent->matrix;
1239 for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1241 if (RSurf_LightCheck(&ent->inversematrix, surf->dlightbits, mesh))
1243 m.numtriangles = mesh->numtriangles;
1244 m.numverts = mesh->numverts;
1245 if (R_Mesh_Draw_GetBuffer(&m, true))
1247 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1248 RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
1249 RSurf_CopyST(mesh->vertex, m.texcoords[0], m.numverts);
1250 R_FillColors(m.color, m.numverts, 0, 0, 0, 1);
1251 RSurf_LightSeparate(&ent->inversematrix, surf->dlightbits, m.numverts, m.vertex, m.color);
1252 RSurf_ScaleColors(m.color, m.colorscale, m.numverts);
1259 static void RSurfShader_OpaqueWall_Pass_Fog(const entity_render_t *ent, const msurface_t *surf)
1262 rmeshbufferinfo_t m;
1264 Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
1265 memset(&m, 0, sizeof(m));
1266 m.blendfunc1 = GL_SRC_ALPHA;
1267 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1268 m.tex[0] = R_GetTexture(surf->currenttexture->fogtexture);
1269 m.matrix = ent->matrix;
1270 for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1272 m.numtriangles = mesh->numtriangles;
1273 m.numverts = mesh->numverts;
1274 if (R_Mesh_Draw_GetBuffer(&m, false))
1276 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1277 RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
1279 RSurf_CopyST(mesh->vertex, m.texcoords[0], m.numverts);
1280 RSurf_FogPassColors(m.vertex, m.color, fogcolor[0], fogcolor[1], fogcolor[2], 1, m.colorscale, m.numverts, modelorg);
1286 static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, const msurface_t *surf)
1289 rmeshbufferinfo_t m;
1290 memset(&m, 0, sizeof(m));
1291 m.blendfunc1 = GL_DST_COLOR;
1292 m.blendfunc2 = GL_SRC_COLOR;
1293 m.tex[0] = R_GetTexture(surf->currenttexture->detailtexture);
1294 m.matrix = ent->matrix;
1295 for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1297 m.numtriangles = mesh->numtriangles;
1298 m.numverts = mesh->numverts;
1299 if (R_Mesh_Draw_GetBuffer(&m, false))
1301 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1302 RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
1303 R_FillColors(m.color, m.numverts, 1, 1, 1, 1);
1304 RSurf_CopyAB(mesh->vertex, m.texcoords[0], m.numverts);
1310 static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const msurface_t *surf)
1313 rmeshbufferinfo_t m;
1314 memset(&m, 0, sizeof(m));
1315 m.blendfunc1 = GL_SRC_ALPHA;
1316 m.blendfunc2 = GL_ONE;
1317 m.tex[0] = R_GetTexture(surf->currenttexture->glowtexture);
1318 m.matrix = ent->matrix;
1319 for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1321 m.numtriangles = mesh->numtriangles;
1322 m.numverts = mesh->numverts;
1323 if (R_Mesh_Draw_GetBuffer(&m, false))
1325 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1326 RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
1327 R_FillColors(m.color, m.numverts, m.colorscale, m.colorscale, m.colorscale, 1);
1328 RSurf_CopyST(mesh->vertex, m.texcoords[0], m.numverts);
1334 static void RSurfShader_Wall_Fullbright_Callback(const void *calldata1, int calldata2)
1336 const entity_render_t *ent = calldata1;
1337 const msurface_t *surf = ent->model->surfaces + calldata2;
1338 RSurfShader_Wall_Pass_BaseFullbright(ent, surf);
1339 if (surf->currenttexture->glowtexture)
1340 RSurfShader_Wall_Pass_Glow(ent, surf);
1342 RSurfShader_Wall_Pass_Fog(ent, surf);
1345 static void RSurfShader_Wall_Fullbright(const entity_render_t *ent, const msurface_t *firstsurf)
1347 const msurface_t *surf;
1349 if (ent->effects & EF_ADDITIVE || ent->alpha < 1)
1351 for (surf = firstsurf;surf;surf = surf->chain)
1353 Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
1354 R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Fullbright_Callback, ent, surf - ent->model->surfaces);
1359 for (surf = firstsurf;surf;surf = surf->chain)
1361 if (surf->currenttexture->fogtexture != NULL)
1363 Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
1364 R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Fullbright_Callback, ent, surf - ent->model->surfaces);
1367 RSurfShader_Wall_Pass_BaseFullbright(ent, surf);
1369 for (surf = firstsurf;surf;surf = surf->chain)
1370 if (surf->currenttexture->glowtexture)
1371 if (surf->currenttexture->fogtexture == NULL)
1372 RSurfShader_Wall_Pass_Glow(ent, surf);
1374 for (surf = firstsurf;surf;surf = surf->chain)
1375 if (surf->currenttexture->fogtexture == NULL)
1376 RSurfShader_Wall_Pass_Fog(ent, surf);
1380 static void RSurfShader_Wall_Vertex_Callback(const void *calldata1, int calldata2)
1382 const entity_render_t *ent = calldata1;
1383 const msurface_t *surf = ent->model->surfaces + calldata2;
1384 RSurfShader_Wall_Pass_BaseVertex(ent, surf);
1385 if (surf->currenttexture->glowtexture)
1386 RSurfShader_Wall_Pass_Glow(ent, surf);
1388 RSurfShader_Wall_Pass_Fog(ent, surf);
1391 static void RSurfShader_Wall_Vertex(const entity_render_t *ent, const msurface_t *firstsurf)
1393 const msurface_t *surf;
1395 if (ent->effects & EF_ADDITIVE || ent->alpha < 1)
1397 for (surf = firstsurf;surf;surf = surf->chain)
1399 Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
1400 R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
1405 for (surf = firstsurf;surf;surf = surf->chain)
1407 if (surf->currenttexture->fogtexture != NULL)
1409 Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
1410 R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
1413 RSurfShader_Wall_Pass_BaseVertex(ent, surf);
1415 for (surf = firstsurf;surf;surf = surf->chain)
1416 if (surf->currenttexture->glowtexture)
1417 if (surf->currenttexture->fogtexture == NULL)
1418 RSurfShader_Wall_Pass_Glow(ent, surf);
1420 for (surf = firstsurf;surf;surf = surf->chain)
1421 if (surf->currenttexture->fogtexture == NULL)
1422 RSurfShader_Wall_Pass_Fog(ent, surf);
1426 static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const msurface_t *firstsurf)
1428 const msurface_t *surf;
1430 if (ent->alpha < 1 || ent->effects & EF_ADDITIVE)
1432 for (surf = firstsurf;surf;surf = surf->chain)
1434 Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
1435 R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
1438 else if (r_vertexsurfaces.integer || ent->alpha < 1 || ent->effects & EF_ADDITIVE)
1440 for (surf = firstsurf;surf;surf = surf->chain)
1442 if (surf->currenttexture->fogtexture != NULL)
1444 Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
1445 R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
1448 RSurfShader_Wall_Pass_BaseVertex(ent, surf);
1450 for (surf = firstsurf;surf;surf = surf->chain)
1451 if (surf->currenttexture->glowtexture)
1452 if (surf->currenttexture->fogtexture == NULL)
1453 RSurfShader_Wall_Pass_Glow(ent, surf);
1455 for (surf = firstsurf;surf;surf = surf->chain)
1456 if (surf->currenttexture->fogtexture == NULL)
1457 RSurfShader_Wall_Pass_Fog(ent, surf);
1461 if (r_textureunits.integer >= 2)
1463 if (r_textureunits.integer >= 3 && gl_combine.integer && r_detailtextures.integer)
1465 for (surf = firstsurf;surf;surf = surf->chain)
1467 if (surf->currenttexture->fogtexture != NULL)
1469 Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
1470 R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
1473 RSurfShader_OpaqueWall_Pass_TripleTexCombine(ent, surf);
1478 for (surf = firstsurf;surf;surf = surf->chain)
1480 if (surf->currenttexture->fogtexture != NULL)
1482 Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
1483 R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
1486 RSurfShader_OpaqueWall_Pass_BaseMTex(ent, surf);
1488 if (r_detailtextures.integer)
1489 for (surf = firstsurf;surf;surf = surf->chain)
1490 if (surf->currenttexture->fogtexture == NULL)
1491 RSurfShader_OpaqueWall_Pass_BaseDetail(ent, surf);
1496 for (surf = firstsurf;surf;surf = surf->chain)
1498 if (surf->currenttexture->fogtexture != NULL)
1500 Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
1501 R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
1504 RSurfShader_OpaqueWall_Pass_BaseTexture(ent, surf);
1506 for (surf = firstsurf;surf;surf = surf->chain)
1507 if (surf->currenttexture->fogtexture == NULL)
1508 RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, surf);
1509 if (r_detailtextures.integer)
1510 for (surf = firstsurf;surf;surf = surf->chain)
1511 if (surf->currenttexture->fogtexture == NULL)
1512 RSurfShader_OpaqueWall_Pass_BaseDetail(ent, surf);
1514 if (!r_dlightmap.integer)
1515 for (surf = firstsurf;surf;surf = surf->chain)
1516 if (surf->dlightframe == r_framecount)
1517 if (surf->currenttexture->fogtexture == NULL)
1518 RSurfShader_OpaqueWall_Pass_Light(ent, surf);
1519 for (surf = firstsurf;surf;surf = surf->chain)
1520 if (surf->currenttexture->glowtexture)
1521 if (surf->currenttexture->fogtexture == NULL)
1522 RSurfShader_OpaqueWall_Pass_Glow(ent, surf);
1524 for (surf = firstsurf;surf;surf = surf->chain)
1525 if (surf->currenttexture->fogtexture == NULL)
1526 RSurfShader_OpaqueWall_Pass_Fog(ent, surf);
1530 Cshader_t Cshader_wall_vertex = {{NULL, RSurfShader_Wall_Vertex}, NULL};
1531 Cshader_t Cshader_wall_lightmap = {{NULL, RSurfShader_Wall_Lightmap}, NULL};
1532 Cshader_t Cshader_wall_fullbright = {{NULL, RSurfShader_Wall_Fullbright}, NULL};
1533 Cshader_t Cshader_water = {{NULL, RSurfShader_Water}, NULL};
1534 Cshader_t Cshader_sky = {{RSurfShader_Sky, NULL}, NULL};
1536 int Cshader_count = 5;
1537 Cshader_t *Cshaders[5] =
1539 &Cshader_wall_vertex,
1540 &Cshader_wall_lightmap,
1541 &Cshader_wall_fullbright,
1546 void R_PrepareSurfaces(entity_render_t *ent)
1548 int i, alttextures, texframe, framecount;
1554 for (i = 0;i < Cshader_count;i++)
1555 Cshaders[i]->chain = NULL;
1558 alttextures = ent->frame != 0;
1559 texframe = (int)(cl.time * 5.0f);
1561 Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
1562 for (i = 0;i < model->nummodelsurfaces;i++)
1564 surf = model->modelsortedsurfaces[i];
1565 if (surf->visframe == r_framecount)
1567 // mark any backface surfaces as not visible
1568 if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
1570 if (!(surf->flags & SURF_PLANEBACK))
1571 surf->visframe = -1;
1575 if (surf->flags & SURF_PLANEBACK)
1576 surf->visframe = -1;
1578 if (surf->visframe == r_framecount)
1581 t = surf->texinfo->texture;
1584 framecount = t->anim_total[alttextures];
1585 if (framecount >= 2)
1586 surf->currenttexture = t->anim_frames[alttextures][texframe % framecount];
1588 surf->currenttexture = t->anim_frames[alttextures][0];
1591 surf->currenttexture = t;
1593 surf->chain = surf->shader->chain;
1594 surf->shader->chain = surf;
1600 void R_DrawSurfaces (entity_render_t *ent, int type)
1605 for (i = 0;i < Cshader_count;i++)
1607 shader = Cshaders[i];
1608 if (shader->chain && shader->shaderfunc[type])
1609 shader->shaderfunc[type](ent, shader->chain);
1613 static void R_DrawPortal_Callback(const void *calldata1, int calldata2)
1617 rmeshbufferinfo_t m;
1618 const entity_render_t *ent = calldata1;
1619 const mportal_t *portal = ent->model->portals + calldata2;
1620 memset(&m, 0, sizeof(m));
1621 m.blendfunc1 = GL_SRC_ALPHA;
1622 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1623 m.numverts = portal->numpoints;
1624 m.numtriangles = portal->numpoints - 2;
1625 m.matrix = ent->matrix;
1626 if (R_Mesh_Draw_GetBuffer(&m, false))
1628 for (i = 0;i < m.numtriangles;i++)
1630 m.index[i * 3 + 0] = 0;
1631 m.index[i * 3 + 1] = i + 1;
1632 m.index[i * 3 + 2] = i + 2;
1634 i = portal - ent->model->portals;
1635 R_FillColors(m.color, m.numverts,
1636 ((i & 0x0007) >> 0) * (1.0f / 7.0f) * m.colorscale,
1637 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * m.colorscale,
1638 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * m.colorscale,
1640 if (PlaneDiff(r_origin, (&portal->plane)) > 0)
1642 for (i = portal->numpoints - 1, v = m.vertex;i >= 0;i--, v += 4)
1643 VectorCopy(portal->points[i].position, v);
1646 for (i = 0, v = m.vertex;i < portal->numpoints;i++, v += 4)
1647 VectorCopy(portal->points[i].position, v);
1652 void R_DrawPortals(entity_render_t *ent)
1655 mportal_t *portal, *endportal;
1656 float temp[3], center[3], f;
1658 if (r_drawportals.integer < 1)
1661 for (portal = ent->model->portals, endportal = portal + ent->model->numportals;portal < endportal;portal++)
1663 if (portal->here->visframe == r_framecount || portal->past->visframe == r_framecount)
1666 for (i = 0;i < portal->numpoints;i++)
1667 VectorAdd(temp, portal->points[i].position, temp);
1668 f = ixtable[portal->numpoints];
1669 VectorScale(temp, f, temp);
1670 Matrix4x4_Transform(&ent->matrix, temp, center);
1671 R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, ent, portal - ent->model->portals);
1676 void R_SetupForBrushModelRendering(entity_render_t *ent)
1683 // because bmodels can be reused, we have to decide which things to render
1684 // from scratch every time
1686 Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
1687 for (i = 0;i < model->nummodelsurfaces;i++)
1689 surf = model->surfaces + model->firstmodelsurface + i;
1690 surf->visframe = r_framecount;
1691 surf->pvsframe = -1;
1692 surf->worldnodeframe = -1;
1693 surf->lightframe = -1;
1694 surf->dlightframe = -1;
1696 R_PrepareSurfaces(ent);
1699 void R_SurfMarkLights (entity_render_t *ent)
1707 if (r_dynamic.integer)
1710 if (!r_vertexsurfaces.integer)
1712 for (i = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;i < ent->model->nummodelsurfaces;i++, surf++)
1714 if (surf->visframe == r_framecount && surf->lightmaptexture != NULL)
1716 if (surf->cached_dlight
1717 || surf->cached_ambient != r_ambient.value
1718 || surf->cached_lightscalebit != lightscalebit)
1719 R_BuildLightMap(ent, surf, false); // base lighting changed
1720 else if (r_dynamic.integer)
1722 if (surf->styles[0] != 255 && (d_lightstylevalue[surf->styles[0]] != surf->cached_light[0]
1723 || (surf->styles[1] != 255 && (d_lightstylevalue[surf->styles[1]] != surf->cached_light[1]
1724 || (surf->styles[2] != 255 && (d_lightstylevalue[surf->styles[2]] != surf->cached_light[2]
1725 || (surf->styles[3] != 255 && (d_lightstylevalue[surf->styles[3]] != surf->cached_light[3]))))))))
1726 R_BuildLightMap(ent, surf, false); // base lighting changed
1727 else if (surf->dlightframe == r_framecount && r_dlightmap.integer)
1728 R_BuildLightMap(ent, surf, true); // only dlights
1735 void R_SurfaceWorldNode (entity_render_t *ent)
1741 // FIXME: R_NotCulledBox is absolute, should be done relative
1742 for (i = 0, surf = model->surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surf++)
1743 if (surf->pvsframe == r_pvsframecount && (!r_cullsurface.integer || R_NotCulledBox (surf->poly_mins, surf->poly_maxs)))
1744 surf->visframe = r_framecount;
1748 static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf)
1751 mportal_t *p, *pstack[8192];
1752 msurface_t *surf, **mark, **endmark;
1754 // LordHavoc: portal-passage worldnode with PVS;
1755 // follows portals leading outward from viewleaf, does not venture
1756 // offscreen or into leafs that are not visible, faster than Quake's
1757 // RecursiveWorldNode
1759 leaf->worldnodeframe = r_framecount;
1763 if (leaf->nummarksurfaces)
1765 for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--)
1768 // make sure surfaces are only processed once
1769 if (surf->worldnodeframe != r_framecount)
1771 surf->worldnodeframe = r_framecount;
1772 if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
1774 if (surf->flags & SURF_PLANEBACK)
1775 surf->visframe = r_framecount;
1779 if (!(surf->flags & SURF_PLANEBACK))
1780 surf->visframe = r_framecount;
1785 // follow portals into other leafs
1786 for (p = leaf->portals;p;p = p->next)
1789 if (leaf->worldnodeframe != r_framecount)
1791 leaf->worldnodeframe = r_framecount;
1792 // FIXME: R_NotCulledBox is absolute, should be done relative
1793 if (leaf->pvsframe == r_pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs))
1795 p->visframe = r_framecount;
1796 pstack[portalstack++] = p;
1799 p = pstack[--portalstack];
1808 static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf)
1810 int c, leafstackpos;
1811 mleaf_t *leaf, *leafstack[8192];
1813 msurface_t *surf, **mark;
1815 // LordHavoc: portal-passage worldnode with PVS;
1816 // follows portals leading outward from viewleaf, does not venture
1817 // offscreen or into leafs that are not visible, faster than Quake's
1818 // RecursiveWorldNode
1819 Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
1820 viewleaf->worldnodeframe = r_framecount;
1821 leafstack[0] = viewleaf;
1823 while (leafstackpos)
1826 leaf = leafstack[--leafstackpos];
1827 // only useful for drawing portals
1828 //leaf->visframe = r_framecount;
1829 // draw any surfaces bounding this leaf
1830 if (leaf->nummarksurfaces)
1832 for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--)
1835 if (!r_cullsurface.integer || R_NotCulledBox (surf->poly_mins, surf->poly_maxs))
1836 surf->visframe = r_framecount;
1839 // follow portals into other leafs
1840 for (p = leaf->portals;p;p = p->next)
1843 if (leaf->worldnodeframe != r_framecount)
1845 leaf->worldnodeframe = r_framecount;
1846 // FIXME: R_NotCulledBox is absolute, should be done relative
1847 if (leaf->pvsframe == r_pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs))
1848 leafstack[leafstackpos++] = leaf;
1855 void R_PVSUpdate (mleaf_t *viewleaf)
1857 int i, j, l, c, bits;
1863 if (r_viewleaf == viewleaf && r_viewleafnovis == r_novis.integer)
1867 r_viewleaf = viewleaf;
1868 r_viewleafnovis = r_novis.integer;
1872 vis = Mod_LeafPVS (viewleaf, cl.worldmodel);
1873 for (j = 0;j < cl.worldmodel->numleafs;j += 8)
1878 l = cl.worldmodel->numleafs - j;
1881 for (i = 0;i < l;i++)
1883 if (bits & (1 << i))
1885 leaf = &cl.worldmodel->leafs[j + i + 1];
1886 // mark surfaces bounding this leaf as visible
1887 for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--)
1888 (*mark++)->pvsframe = r_pvsframecount;
1889 // mark parents as visible until we hit an already
1890 // marked parent (which is usually very soon)
1891 for (node = (mnode_t *)leaf;node && node->pvsframe != r_pvsframecount;node = node->parent)
1892 node->pvsframe = r_pvsframecount;
1905 void R_DrawWorld (entity_render_t *ent)
1907 // there is only one instance of the world, but it can be rendered in
1910 viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
1911 R_PVSUpdate(viewleaf);
1914 if (r_surfaceworldnode.integer || viewleaf->contents == CONTENTS_SOLID)
1915 R_SurfaceWorldNode (ent);
1917 R_PortalWorldNode (ent, viewleaf);
1925 void R_DrawBrushModelSky (entity_render_t *ent)
1927 R_SetupForBrushModelRendering(ent);
1928 R_DrawSurfaces(ent, SHADERSTAGE_SKY);
1931 void R_DrawBrushModelNormal (entity_render_t *ent)
1934 // have to flush queue because of possible lightmap reuse
1936 R_SetupForBrushModelRendering(ent);
1937 R_SurfMarkLights(ent);
1938 R_DrawSurfaces(ent, SHADERSTAGE_NORMAL);
1941 static void gl_surf_start(void)
1945 static void gl_surf_shutdown(void)
1949 static void gl_surf_newmap(void)
1951 // reset pvs visibility variables so it will update on first frame
1952 r_pvsframecount = 1;
1954 r_viewleafnovis = false;
1957 void GL_Surf_Init(void)
1960 dlightdivtable[0] = 4194304;
1961 for (i = 1;i < 32768;i++)
1962 dlightdivtable[i] = 4194304 / (i << 7);
1964 Cvar_RegisterVariable(&r_ambient);
1965 Cvar_RegisterVariable(&r_vertexsurfaces);
1966 Cvar_RegisterVariable(&r_dlightmap);
1967 Cvar_RegisterVariable(&r_drawportals);
1968 Cvar_RegisterVariable(&r_testvis);
1969 Cvar_RegisterVariable(&r_floatbuildlightmap);
1970 Cvar_RegisterVariable(&r_detailtextures);
1971 Cvar_RegisterVariable(&r_surfaceworldnode);
1972 Cvar_RegisterVariable(&r_cullsurface);
1974 R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap);