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 signed int blocklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*3]; // LordHavoc: *3 for colored lighting
28 static byte templight[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*4];
30 cvar_t r_ambient = {0, "r_ambient", "0"};
31 cvar_t r_vertexsurfaces = {0, "r_vertexsurfaces", "0"};
32 cvar_t r_dlightmap = {CVAR_SAVE, "r_dlightmap", "1"};
33 cvar_t r_drawportals = {0, "r_drawportals", "0"};
34 cvar_t r_testvis = {0, "r_testvis", "0"};
36 static void gl_surf_start(void)
40 static void gl_surf_shutdown(void)
44 static void gl_surf_newmap(void)
48 void GL_Surf_Init(void)
50 Cvar_RegisterVariable(&r_ambient);
51 Cvar_RegisterVariable(&r_vertexsurfaces);
52 Cvar_RegisterVariable(&r_dlightmap);
53 Cvar_RegisterVariable(&r_drawportals);
54 Cvar_RegisterVariable(&r_testvis);
56 R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap);
59 static int dlightdivtable[32768];
61 static int R_AddDynamicLights (msurface_t *surf)
63 int sdtable[18], lnum, td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, smax3, red, green, blue, lit, dist2, impacts, impactt, subtract;
68 // LordHavoc: use 64bit integer... shame it's not very standardized...
69 #if _MSC_VER || __BORLANDC__
77 if (!dlightdivtable[1])
79 dlightdivtable[0] = 4194304;
80 for (s = 1; s < 32768; s++)
81 dlightdivtable[s] = 4194304 / (s << 7);
84 smax = (surf->extents[0] >> 4) + 1;
85 tmax = (surf->extents[1] >> 4) + 1;
87 for (lnum = 0; lnum < r_numdlights; lnum++)
89 if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31))))
90 continue; // not lit by this light
92 softwareuntransform(r_dlight[lnum].origin, local);
93 // VectorSubtract (r_dlight[lnum].origin, currentrenderentity->origin, local);
94 dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
96 // for comparisons to minimum acceptable light
97 maxdist = (int) r_dlight[lnum].cullradius2;
99 // already clamped, skip this
100 // clamp radius to avoid exceeding 32768 entry division table
101 //if (maxdist > 4194304)
102 // maxdist = 4194304;
105 dist2 += LIGHTOFFSET;
106 if (dist2 >= maxdist)
109 impact[0] = local[0] - surf->plane->normal[0] * dist;
110 impact[1] = local[1] - surf->plane->normal[1] * dist;
111 impact[2] = local[2] - surf->plane->normal[2] * dist;
113 impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
114 impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
116 s = bound(0, impacts, smax * 16) - impacts;
117 t = bound(0, impactt, tmax * 16) - impactt;
118 i = s * s + t * t + dist2;
122 // reduce calculations
123 for (s = 0, i = impacts; s < smax; s++, i -= 16)
124 sdtable[s] = i * i + dist2;
126 maxdist3 = maxdist - dist2;
128 // convert to 8.8 blocklights format
129 red = r_dlight[lnum].light[0];
130 green = r_dlight[lnum].light[1];
131 blue = r_dlight[lnum].light[2];
132 subtract = (int) (r_dlight[lnum].lightsubtract * 4194304.0f);
137 for (t = 0;t < tmax;t++, i -= 16)
140 // make sure some part of it is visible on this line
143 maxdist2 = maxdist - td;
144 for (s = 0;s < smax;s++)
146 if (sdtable[s] < maxdist2)
148 k = dlightdivtable[(sdtable[s] + td) >> 7] - subtract;
151 bl[0] += (red * k) >> 8;
152 bl[1] += (green * k) >> 8;
153 bl[2] += (blue * k) >> 8;
171 Combine and scale multiple lightmaps into the 8.8 format in blocklights
174 static void R_BuildLightMap (msurface_t *surf, int dlightchanged)
176 int smax, tmax, i, j, size, size3, shift, scale, maps, *bl, stride, l;
177 byte *lightmap, *out;
179 // update cached lighting info
180 surf->cached_dlight = 0;
181 surf->cached_lightscalebit = lightscalebit;
182 surf->cached_ambient = r_ambient.value;
183 surf->cached_light[0] = d_lightstylevalue[surf->styles[0]];
184 surf->cached_light[1] = d_lightstylevalue[surf->styles[1]];
185 surf->cached_light[2] = d_lightstylevalue[surf->styles[2]];
186 surf->cached_light[3] = d_lightstylevalue[surf->styles[3]];
188 smax = (surf->extents[0]>>4)+1;
189 tmax = (surf->extents[1]>>4)+1;
192 lightmap = surf->samples;
194 // set to full bright if no light data
195 if ((currentrenderentity->effects & EF_FULLBRIGHT) || !cl.worldmodel->lightdata)
198 for (i = 0;i < size;i++)
208 j = r_ambient.value * 512.0f; // would be 256.0f logically, but using 512.0f to match winquake style
212 for (i = 0;i < size3;i++)
216 memset(&blocklights[0], 0, size*3*sizeof(int));
218 if (surf->dlightframe == r_framecount && r_dlightmap.integer)
220 surf->cached_dlight = R_AddDynamicLights(surf);
221 if (surf->cached_dlight)
223 else if (dlightchanged)
224 return; // don't upload if only updating dlights and none mattered
227 // add all the lightmaps
229 for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++)
230 for (scale = d_lightstylevalue[surf->styles[maps]], bl = blocklights, i = 0;i < size3;i++)
231 *bl++ += *lightmap++ * scale;
236 // deal with lightmap brightness scale
237 shift = 7 + lightscalebit;
238 if (currentrenderentity->model->lightmaprgba)
240 stride = (surf->lightmaptexturestride - smax) * 4;
241 for (i = 0;i < tmax;i++, out += stride)
243 for (j = 0;j < smax;j++)
245 l = *bl++ >> shift;*out++ = min(l, 255);
246 l = *bl++ >> shift;*out++ = min(l, 255);
247 l = *bl++ >> shift;*out++ = min(l, 255);
254 stride = (surf->lightmaptexturestride - smax) * 3;
255 for (i = 0;i < tmax;i++, out += stride)
257 for (j = 0;j < smax;j++)
259 l = *bl++ >> shift;*out++ = min(l, 255);
260 l = *bl++ >> shift;*out++ = min(l, 255);
261 l = *bl++ >> shift;*out++ = min(l, 255);
266 R_UpdateTexture(surf->lightmaptexture, templight);
273 Returns the proper texture for a given time and base texture
277 // note: this was manually inlined in R_PrepareSurfaces
278 static texture_t *R_TextureAnimation (texture_t *base)
280 if (currentrenderentity->frame && base->alternate_anims != NULL)
281 base = base->alternate_anims;
283 if (base->anim_total < 2)
286 return base->anim_frames[(int)(cl.time * 5.0f) % base->anim_total];
292 =============================================================
296 =============================================================
300 static float turbsin[256] =
302 #include "gl_warp_sin.h"
304 #define TURBSCALE (256.0 / (2 * M_PI))
306 #define MAX_SURFVERTS 1024
315 static surfvert_t svert[MAX_SURFVERTS]; // used by the following functions
317 static int RSurfShader_Sky(int stage, msurface_t *s)
320 float number, length, dir[3], speedscale;
325 // LordHavoc: HalfLife maps have freaky skypolys...
326 if (currentrenderentity->model->ishlbsp)
335 skyrendernow = false;
338 // draw depth-only polys
339 memset(&m, 0, sizeof(m));
340 m.transparent = false;
341 m.blendfunc1 = GL_ZERO;
342 m.blendfunc2 = GL_ONE;
344 m.numtriangles = s->mesh.numtriangles;
345 m.numverts = s->mesh.numverts;
346 m.index = s->mesh.index;
351 if (softwaretransform_complexity)
353 m.vertex = &svert[0].v[0];
354 m.vertexstep = sizeof(surfvert_t);
355 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
356 softwaretransform(v->v, sv->v);
360 m.vertex = &s->mesh.vertex[0].v[0];
361 m.vertexstep = sizeof(surfvertex_t);
365 else if (skyrenderglquake)
367 memset(&m, 0, sizeof(m));
368 m.transparent = false;
369 m.blendfunc1 = GL_ONE;
370 m.blendfunc2 = GL_ZERO;
371 m.numtriangles = s->mesh.numtriangles;
372 m.numverts = s->mesh.numverts;
373 m.index = s->mesh.index;
374 m.vertex = &svert[0].v[0];
375 m.vertexstep = sizeof(surfvert_t);
380 if (r_mergesky.integer)
381 m.tex[0] = R_GetTexture(mergeskytexture);
383 m.tex[0] = R_GetTexture(solidskytexture);
384 m.texcoords[0] = &svert[0].st[0];
385 m.texcoordstep[0] = sizeof(surfvert_t);
386 speedscale = cl.time * (8.0/128.0);
387 speedscale -= (int)speedscale;
388 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
390 softwaretransform(v->v, sv->v);
391 VectorSubtract (sv->v, r_origin, dir);
392 // flatten the sphere
395 number = DotProduct(dir, dir);
397 length = 3.0f / sqrt(number);
399 *((long *)&length) = 0x5f3759df - ((* (long *) &number) >> 1);
400 length = 3.0f * (length * (1.5f - (number * 0.5f * length * length)));
403 sv->st[0] = speedscale + dir[0] * length;
404 sv->st[1] = speedscale + dir[1] * length;
411 memset(&m, 0, sizeof(m));
412 m.transparent = false;
413 m.blendfunc1 = GL_ONE;
414 m.blendfunc2 = GL_ZERO;
415 m.numtriangles = s->mesh.numtriangles;
416 m.numverts = s->mesh.numverts;
417 m.index = s->mesh.index;
422 if (softwaretransform_complexity)
424 m.vertex = &svert[0].v[0];
425 m.vertexstep = sizeof(surfvert_t);
426 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
427 softwaretransform(v->v, sv->v);
431 m.vertex = &s->mesh.vertex[0].v[0];
432 m.vertexstep = sizeof(surfvertex_t);
440 if (skyrenderglquake && !r_mergesky.integer)
442 memset(&m, 0, sizeof(m));
443 m.transparent = false;
444 m.blendfunc1 = GL_SRC_ALPHA;
445 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
446 m.numtriangles = s->mesh.numtriangles;
447 m.numverts = s->mesh.numverts;
448 m.index = s->mesh.index;
449 m.vertex = &svert[0].v[0];
450 m.vertexstep = sizeof(surfvert_t);
455 m.tex[0] = R_GetTexture(alphaskytexture);
456 m.texcoords[0] = &svert[0].st[0];
457 m.texcoordstep[0] = sizeof(surfvert_t);
458 speedscale = cl.time * (16.0/128.0);
459 speedscale -= (int)speedscale;
460 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
462 softwaretransform(v->v, sv->v);
463 VectorSubtract (sv->v, r_origin, dir);
464 // flatten the sphere
467 number = DotProduct(dir, dir);
469 length = 3.0f / sqrt(number);
471 *((long *)&length) = 0x5f3759df - ((* (long *) &number) >> 1);
472 length = 3.0f * (length * (1.5f - (number * 0.5f * length * length)));
475 sv->st[0] = speedscale + dir[0] * length;
476 sv->st[1] = speedscale + dir[1] * length;
487 static int RSurf_Light(int *dlightbits, int numverts)
490 int i, l, lit = false;
494 for (l = 0;l < r_numdlights;l++)
496 if (dlightbits[l >> 5] & (1 << (l & 31)))
499 // FIXME: support softwareuntransform here and make bmodels use hardware transform?
500 VectorCopy(rd->origin, lightorigin);
501 for (i = 0, sv = svert;i < numverts;i++, sv++)
503 f = VectorDistance2(sv->v, lightorigin) + LIGHTOFFSET;
504 if (f < rd->cullradius2)
506 f = (1.0f / f) - rd->lightsubtract;
507 sv->c[0] += rd->light[0] * f;
508 sv->c[1] += rd->light[1] * f;
509 sv->c[2] += rd->light[2] * f;
518 static void RSurfShader_Water_Pass_Base(msurface_t *s)
521 float diff[3], alpha, ifog;
525 alpha = currentrenderentity->alpha * (s->flags & SURF_DRAWNOALPHA ? 1 : r_wateralpha.value);
527 memset(&m, 0, sizeof(m));
528 if (alpha != 1 || s->currenttexture->fogtexture != NULL)
530 m.transparent = true;
531 m.blendfunc1 = GL_SRC_ALPHA;
532 m.blendfunc2 = GL_ONE; //_MINUS_SRC_ALPHA;
536 m.transparent = false;
537 m.blendfunc1 = GL_ONE;
538 m.blendfunc2 = GL_ZERO;
540 m.numtriangles = s->mesh.numtriangles;
541 m.numverts = s->mesh.numverts;
542 m.index = s->mesh.index;
543 m.vertex = &svert[0].v[0];
544 m.vertexstep = sizeof(surfvert_t);
545 m.color = &svert[0].c[0];
546 m.colorstep = sizeof(surfvert_t);
547 m.tex[0] = R_GetTexture(s->currenttexture->texture);
548 m.texcoords[0] = &svert[0].st[0];
549 m.texcoordstep[0] = sizeof(surfvert_t);
550 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
552 softwaretransform(v->v, sv->v);
553 if (r_waterripple.value)
554 sv->v[2] += r_waterripple.value * (1.0f / 64.0f) * turbsin[(int)((v->v[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((v->v[1]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255];
555 if (s->flags & SURF_DRAWFULLBRIGHT)
569 sv->st[0] = (v->st[0] + turbsin[(int)((v->st[1]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f);
570 sv->st[1] = (v->st[1] + turbsin[(int)((v->st[0]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f);
572 if (s->dlightframe == r_framecount && !(s->flags & SURF_DRAWFULLBRIGHT))
573 RSurf_Light(s->dlightbits, m.numverts);
574 if (fogenabled/* && m.blendfunc2 == GL_ONE_MINUS_SRC_ALPHA*/)
576 for (i = 0, sv = svert;i < m.numverts;i++, sv++)
578 VectorSubtract(sv->v, r_origin, diff);
579 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
588 static void RSurfShader_Water_Pass_Glow(msurface_t *s)
591 float diff[3], alpha, ifog;
595 alpha = currentrenderentity->alpha * (s->flags & SURF_DRAWNOALPHA ? 1 : r_wateralpha.value);
597 memset(&m, 0, sizeof(m));
598 m.transparent = alpha != 1 || s->currenttexture->fogtexture != NULL;
599 m.blendfunc1 = GL_SRC_ALPHA;
600 m.blendfunc2 = GL_ONE;
601 m.numtriangles = s->mesh.numtriangles;
602 m.numverts = s->mesh.numverts;
603 m.index = s->mesh.index;
604 m.vertex = &svert[0].v[0];
605 m.vertexstep = sizeof(surfvert_t);
610 m.tex[0] = R_GetTexture(s->currenttexture->glowtexture);
611 m.texcoords[0] = &svert[0].st[0];
612 m.texcoordstep[0] = sizeof(surfvert_t);
615 m.color = &svert[0].c[0];
616 m.colorstep = sizeof(surfvert_t);
617 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
619 softwaretransform(v->v, sv->v);
620 if (r_waterripple.value)
621 sv->v[2] += r_waterripple.value * (1.0f / 64.0f) * turbsin[(int)((v->v[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((v->v[1]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255];
622 sv->st[0] = (v->st[0] + turbsin[(int)((v->st[1]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f);
623 sv->st[1] = (v->st[1] + turbsin[(int)((v->st[0]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f);
624 VectorSubtract(sv->v, r_origin, diff);
625 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
626 sv->c[0] = m.cr * ifog;
627 sv->c[1] = m.cg * ifog;
628 sv->c[2] = m.cb * ifog;
634 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
636 softwaretransform(v->v, sv->v);
637 if (r_waterripple.value)
638 sv->v[2] += r_waterripple.value * (1.0f / 64.0f) * turbsin[(int)((v->v[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((v->v[1]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255];
639 sv->st[0] = (v->st[0] + turbsin[(int)((v->st[1]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f);
640 sv->st[1] = (v->st[1] + turbsin[(int)((v->st[0]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f);
646 static void RSurfShader_Water_Pass_Fog(msurface_t *s)
654 alpha = currentrenderentity->alpha * (s->flags & SURF_DRAWNOALPHA ? 1 : r_wateralpha.value);
656 memset(&m, 0, sizeof(m));
657 m.transparent = alpha != 1 || s->currenttexture->fogtexture != NULL;
658 m.blendfunc1 = GL_SRC_ALPHA;
659 m.blendfunc2 = GL_ONE;
660 m.numtriangles = s->mesh.numtriangles;
661 m.numverts = s->mesh.numverts;
662 m.index = s->mesh.index;
663 m.vertex = &svert[0].v[0];
664 m.vertexstep = sizeof(surfvert_t);
665 m.color = &svert[0].c[0];
666 m.colorstep = sizeof(surfvert_t);
667 m.tex[0] = R_GetTexture(s->currenttexture->fogtexture);
668 m.texcoords[0] = &svert[0].st[0];
669 m.texcoordstep[0] = sizeof(surfvert_t);
671 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
673 softwaretransform(v->v, sv->v);
674 if (r_waterripple.value)
675 sv->v[2] += r_waterripple.value * (1.0f / 64.0f) * turbsin[(int)((v->v[0]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255] * turbsin[(int)((v->v[1]*(1.0f/32.0f)+cl.time) * TURBSCALE) & 255];
678 sv->st[0] = (v->st[0] + turbsin[(int)((v->st[1]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f);
679 sv->st[1] = (v->st[1] + turbsin[(int)((v->st[0]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f);
681 VectorSubtract(sv->v, r_origin, diff);
682 sv->c[0] = fogcolor[0];
683 sv->c[1] = fogcolor[1];
684 sv->c[2] = fogcolor[2];
685 sv->c[3] = alpha * exp(fogdensity/DotProduct(diff, diff));
690 static int RSurfShader_Water(int stage, msurface_t *s)
695 RSurfShader_Water_Pass_Base(s);
698 if (s->currenttexture->glowtexture)
699 RSurfShader_Water_Pass_Glow(s);
702 if (fogenabled && (s->flags & SURF_DRAWNOALPHA))
704 RSurfShader_Water_Pass_Fog(s);
714 static void RSurfShader_Wall_Pass_BaseMTex(msurface_t *s)
722 memset(&m, 0, sizeof(m));
723 if (currentrenderentity->effects & EF_ADDITIVE)
725 m.transparent = true;
726 m.blendfunc1 = GL_SRC_ALPHA;
727 m.blendfunc2 = GL_ONE;
729 else if (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
731 m.transparent = true;
732 m.blendfunc1 = GL_SRC_ALPHA;
733 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
737 m.transparent = false;
738 m.blendfunc1 = GL_ONE;
739 m.blendfunc2 = GL_ZERO;
741 m.numtriangles = s->mesh.numtriangles;
742 m.numverts = s->mesh.numverts;
743 m.index = s->mesh.index;
747 if (gl_combine.integer)
751 m.ca = currentrenderentity->alpha;
752 m.tex[0] = R_GetTexture(s->currenttexture->texture);
753 m.tex[1] = R_GetTexture(s->lightmaptexture);
754 m.texcoords[0] = &s->mesh.vertex->st[0];
755 m.texcoords[1] = &s->mesh.vertex->uv[0];
756 m.texcoordstep[0] = sizeof(surfvertex_t);
757 m.texcoordstep[1] = sizeof(surfvertex_t);
760 m.color = &svert[0].c[0];
761 m.colorstep = sizeof(surfvert_t);
762 if (softwaretransform_complexity)
764 m.vertex = &svert[0].v[0];
765 m.vertexstep = sizeof(surfvert_t);
766 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
768 softwaretransform(v->v, sv->v);
769 VectorSubtract(sv->v, r_origin, diff);
770 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
771 sv->c[0] = m.cr * ifog;
772 sv->c[1] = m.cg * ifog;
773 sv->c[2] = m.cb * ifog;
779 m.vertex = &s->mesh.vertex->v[0];
780 m.vertexstep = sizeof(surfvertex_t);
781 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
783 VectorSubtract(v->v, r_origin, diff);
784 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
785 sv->c[0] = m.cr * ifog;
786 sv->c[1] = m.cg * ifog;
787 sv->c[2] = m.cb * ifog;
794 if (softwaretransform_complexity)
796 m.vertex = &svert[0].v[0];
797 m.vertexstep = sizeof(surfvert_t);
798 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
799 softwaretransform(v->v, sv->v);
803 m.vertex = &s->mesh.vertex->v[0];
804 m.vertexstep = sizeof(surfvertex_t);
810 static void RSurfShader_Wall_Pass_BaseTexture(msurface_t *s)
817 memset(&m, 0, sizeof(m));
818 m.transparent = false;
819 m.blendfunc1 = GL_ONE;
820 m.blendfunc2 = GL_ZERO;
821 m.numtriangles = s->mesh.numtriangles;
822 m.numverts = s->mesh.numverts;
823 m.index = s->mesh.index;
837 m.tex[0] = R_GetTexture(s->currenttexture->texture);
838 m.texcoords[0] = &s->mesh.vertex->st[0];
839 m.texcoordstep[0] = sizeof(surfvertex_t);
840 if (softwaretransform_complexity)
842 m.vertex = &svert[0].v[0];
843 m.vertexstep = sizeof(surfvert_t);
844 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
845 softwaretransform(v->v, sv->v);
849 m.vertex = &s->mesh.vertex->v[0];
850 m.vertexstep = sizeof(surfvertex_t);
855 static void RSurfShader_Wall_Pass_BaseLightmap(msurface_t *s)
863 memset(&m, 0, sizeof(m));
864 m.transparent = false;
865 m.blendfunc1 = GL_ZERO;
866 m.blendfunc2 = GL_SRC_COLOR;
867 m.numtriangles = s->mesh.numtriangles;
868 m.numverts = s->mesh.numverts;
869 m.index = s->mesh.index;
876 m.tex[0] = R_GetTexture(s->lightmaptexture);
877 m.texcoords[0] = &s->mesh.vertex->uv[0];
878 m.texcoordstep[0] = sizeof(surfvertex_t);
881 m.color = &svert[0].c[0];
882 m.colorstep = sizeof(surfvert_t);
883 if (softwaretransform_complexity)
885 m.vertex = &svert[0].v[0];
886 m.vertexstep = sizeof(surfvert_t);
887 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
889 softwaretransform(v->v, sv->v);
890 VectorSubtract(sv->v, r_origin, diff);
891 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
892 sv->c[0] = m.cr * ifog;
893 sv->c[1] = m.cg * ifog;
894 sv->c[2] = m.cb * ifog;
900 m.vertex = &s->mesh.vertex->v[0];
901 m.vertexstep = sizeof(surfvertex_t);
902 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
904 VectorSubtract(v->v, r_origin, diff);
905 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
906 sv->c[0] = m.cr * ifog;
907 sv->c[1] = m.cg * ifog;
908 sv->c[2] = m.cb * ifog;
915 if (softwaretransform_complexity)
917 m.vertex = &svert[0].v[0];
918 m.vertexstep = sizeof(surfvert_t);
919 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
920 softwaretransform(v->v, sv->v);
924 m.vertex = &s->mesh.vertex->v[0];
925 m.vertexstep = sizeof(surfvertex_t);
931 static void RSurfShader_Wall_Pass_BaseVertex(msurface_t *s)
934 float c[3], base[3], scale, diff[3], ifog;
940 size3 = ((s->extents[0]>>4)+1)*((s->extents[1]>>4)+1)*3;
942 base[0] = base[1] = base[2] = r_ambient.value * (1.0f / 128.0f);
944 memset(&m, 0, sizeof(m));
945 if (currentrenderentity->effects & EF_ADDITIVE)
947 m.transparent = true;
948 m.blendfunc1 = GL_SRC_ALPHA;
949 m.blendfunc2 = GL_ONE;
951 else if (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
953 m.transparent = true;
954 m.blendfunc1 = GL_SRC_ALPHA;
955 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
959 m.transparent = false;
960 m.blendfunc1 = GL_ONE;
961 m.blendfunc2 = GL_ZERO;
963 m.numtriangles = s->mesh.numtriangles;
964 m.numverts = s->mesh.numverts;
965 m.index = s->mesh.index;
966 m.vertex = &svert[0].v[0];
967 m.vertexstep = sizeof(surfvert_t);
968 m.color = &svert[0].c[0];
969 m.colorstep = sizeof(surfvert_t);
970 m.tex[0] = R_GetTexture(s->currenttexture->texture);
971 m.texcoords[0] = &s->mesh.vertex->st[0];
972 m.texcoordstep[0] = sizeof(surfvertex_t);
973 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
975 softwaretransform(v->v, sv->v);
977 if (s->styles[0] != 255)
979 lm = s->samples + v->lightmapoffset;
980 scale = d_lightstylevalue[s->styles[0]] * (1.0f / 32768.0f);
981 VectorMA(c, scale, lm, c);
982 if (s->styles[1] != 255)
985 scale = d_lightstylevalue[s->styles[1]] * (1.0f / 32768.0f);
986 VectorMA(c, scale, lm, c);
987 if (s->styles[2] != 255)
990 scale = d_lightstylevalue[s->styles[2]] * (1.0f / 32768.0f);
991 VectorMA(c, scale, lm, c);
992 if (s->styles[3] != 255)
995 scale = d_lightstylevalue[s->styles[3]] * (1.0f / 32768.0f);
996 VectorMA(c, scale, lm, c);
1004 sv->c[3] = currentrenderentity->alpha;
1006 if (s->dlightframe == r_framecount)
1007 RSurf_Light(s->dlightbits, m.numverts);
1010 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
1012 VectorSubtract(sv->v, r_origin, diff);
1013 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
1022 static void RSurfShader_Wall_Pass_BaseFullbright(msurface_t *s)
1025 float diff[3], ifog;
1030 memset(&m, 0, sizeof(m));
1031 if (currentrenderentity->effects & EF_ADDITIVE)
1033 m.transparent = true;
1034 m.blendfunc1 = GL_SRC_ALPHA;
1035 m.blendfunc2 = GL_ONE;
1037 else if (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
1039 m.transparent = true;
1040 m.blendfunc1 = GL_SRC_ALPHA;
1041 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1045 m.transparent = false;
1046 m.blendfunc1 = GL_ONE;
1047 m.blendfunc2 = GL_ZERO;
1049 m.numtriangles = s->mesh.numtriangles;
1050 m.numverts = s->mesh.numverts;
1051 m.index = s->mesh.index;
1052 m.vertex = &svert[0].v[0];
1053 m.vertexstep = sizeof(surfvert_t);
1054 m.tex[0] = R_GetTexture(s->currenttexture->texture);
1055 m.texcoords[0] = &s->mesh.vertex->st[0];
1056 m.texcoordstep[0] = sizeof(surfvertex_t);
1059 m.color = &svert[0].c[0];
1060 m.colorstep = sizeof(surfvert_t);
1061 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
1063 softwaretransform(v->v, sv->v);
1064 VectorSubtract(sv->v, r_origin, diff);
1065 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
1069 sv->c[3] = currentrenderentity->alpha;
1074 m.cr = m.cg = m.cb = 1;
1075 m.ca = currentrenderentity->alpha;
1076 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
1077 softwaretransform(v->v, sv->v);
1082 static void RSurfShader_Wall_Pass_Light(msurface_t *s)
1085 float diff[3], ifog;
1090 memset(&m, 0, sizeof(m));
1091 if (currentrenderentity->effects & EF_ADDITIVE)
1092 m.transparent = true;
1093 else if (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
1094 m.transparent = true;
1096 m.transparent = false;
1097 m.blendfunc1 = GL_SRC_ALPHA;
1098 m.blendfunc2 = GL_ONE;
1099 m.numtriangles = s->mesh.numtriangles;
1100 m.numverts = s->mesh.numverts;
1101 m.index = s->mesh.index;
1102 m.vertex = &svert[0].v[0];
1103 m.vertexstep = sizeof(surfvert_t);
1104 m.color = &svert[0].c[0];
1105 m.colorstep = sizeof(surfvert_t);
1106 m.tex[0] = R_GetTexture(s->currenttexture->texture);
1107 m.texcoords[0] = &s->mesh.vertex->st[0];
1108 m.texcoordstep[0] = sizeof(surfvertex_t);
1109 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
1111 softwaretransform(v->v, sv->v);
1115 sv->c[3] = currentrenderentity->alpha;
1117 if (RSurf_Light(s->dlightbits, m.numverts))
1121 for (i = 0, sv = svert;i < m.numverts;i++, sv++)
1123 VectorSubtract(sv->v, r_origin, diff);
1124 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
1134 static void RSurfShader_Wall_Pass_Glow(msurface_t *s)
1137 float diff[3], ifog;
1142 memset(&m, 0, sizeof(m));
1143 if (currentrenderentity->effects & EF_ADDITIVE)
1144 m.transparent = true;
1145 else if (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
1146 m.transparent = true;
1148 m.transparent = false;
1149 m.blendfunc1 = GL_SRC_ALPHA;
1150 m.blendfunc2 = GL_ONE;
1151 m.numtriangles = s->mesh.numtriangles;
1152 m.numverts = s->mesh.numverts;
1153 m.index = s->mesh.index;
1157 m.ca = currentrenderentity->alpha;
1158 m.tex[0] = R_GetTexture(s->currenttexture->glowtexture);
1159 m.texcoords[0] = &s->mesh.vertex->st[0];
1160 m.texcoordstep[0] = sizeof(surfvertex_t);
1163 m.color = &svert[0].c[0];
1164 m.colorstep = sizeof(surfvert_t);
1165 if (softwaretransform_complexity)
1167 m.vertex = &svert[0].v[0];
1168 m.vertexstep = sizeof(surfvert_t);
1169 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
1171 softwaretransform(v->v, sv->v);
1172 VectorSubtract(sv->v, r_origin, diff);
1173 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
1174 sv->c[0] = m.cr * ifog;
1175 sv->c[1] = m.cg * ifog;
1176 sv->c[2] = m.cb * ifog;
1182 m.vertex = &s->mesh.vertex->v[0];
1183 m.vertexstep = sizeof(surfvertex_t);
1184 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
1186 VectorSubtract(v->v, r_origin, diff);
1187 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
1188 sv->c[0] = m.cr * ifog;
1189 sv->c[1] = m.cg * ifog;
1190 sv->c[2] = m.cb * ifog;
1197 if (softwaretransform_complexity)
1199 m.vertex = &svert[0].v[0];
1200 m.vertexstep = sizeof(surfvert_t);
1201 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
1202 softwaretransform(v->v, sv->v);
1206 m.vertex = &s->mesh.vertex->v[0];
1207 m.vertexstep = sizeof(surfvertex_t);
1213 static void RSurfShader_Wall_Pass_Fog(msurface_t *s)
1221 memset(&m, 0, sizeof(m));
1222 if (currentrenderentity->effects & EF_ADDITIVE)
1223 m.transparent = true;
1224 else if (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
1225 m.transparent = true;
1227 m.transparent = false;
1228 m.blendfunc1 = GL_SRC_ALPHA;
1229 m.blendfunc2 = GL_ONE;
1230 m.numtriangles = s->mesh.numtriangles;
1231 m.numverts = s->mesh.numverts;
1232 m.index = s->mesh.index;
1233 m.color = &svert[0].c[0];
1234 m.colorstep = sizeof(surfvert_t);
1235 m.tex[0] = R_GetTexture(s->currenttexture->fogtexture);
1236 m.texcoords[0] = &s->mesh.vertex->st[0];
1237 m.texcoordstep[0] = sizeof(surfvertex_t);
1238 if (softwaretransform_complexity)
1240 m.vertex = &svert[0].v[0];
1241 m.vertexstep = sizeof(surfvert_t);
1242 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
1244 softwaretransform(v->v, sv->v);
1245 VectorSubtract(sv->v, r_origin, diff);
1246 sv->c[0] = fogcolor[0];
1247 sv->c[1] = fogcolor[1];
1248 sv->c[2] = fogcolor[2];
1249 sv->c[3] = currentrenderentity->alpha * exp(fogdensity/DotProduct(diff,diff));
1254 m.vertex = &s->mesh.vertex->v[0];
1255 m.vertexstep = sizeof(surfvertex_t);
1256 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
1258 VectorSubtract(v->v, r_origin, diff);
1259 sv->c[0] = fogcolor[0];
1260 sv->c[1] = fogcolor[1];
1261 sv->c[2] = fogcolor[2];
1262 sv->c[3] = currentrenderentity->alpha * exp(fogdensity/DotProduct(diff,diff));
1268 static int RSurfShader_Wall_Fullbright(int stage, msurface_t *s)
1273 RSurfShader_Wall_Pass_BaseFullbright(s);
1276 if (s->currenttexture->glowtexture)
1277 RSurfShader_Wall_Pass_Glow(s);
1284 static int RSurfShader_Wall_Vertex(int stage, msurface_t *s)
1289 RSurfShader_Wall_Pass_BaseVertex(s);
1292 if (s->currenttexture->glowtexture)
1293 RSurfShader_Wall_Pass_Glow(s);
1300 static int RSurfShader_Wall_Lightmap(int stage, msurface_t *s)
1302 if (r_vertexsurfaces.integer)
1307 RSurfShader_Wall_Pass_BaseVertex(s);
1310 if (s->currenttexture->glowtexture)
1311 RSurfShader_Wall_Pass_Glow(s);
1317 else if (r_multitexture.integer)
1319 if (r_dlightmap.integer)
1324 RSurfShader_Wall_Pass_BaseMTex(s);
1327 if (s->currenttexture->glowtexture)
1328 RSurfShader_Wall_Pass_Glow(s);
1339 RSurfShader_Wall_Pass_BaseMTex(s);
1342 if (s->dlightframe == r_framecount)
1343 RSurfShader_Wall_Pass_Light(s);
1346 if (s->currenttexture->glowtexture)
1347 RSurfShader_Wall_Pass_Glow(s);
1354 else if (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1 || currentrenderentity->effects & EF_ADDITIVE)
1359 RSurfShader_Wall_Pass_BaseVertex(s);
1362 if (s->currenttexture->glowtexture)
1363 RSurfShader_Wall_Pass_Glow(s);
1371 if (r_dlightmap.integer)
1376 RSurfShader_Wall_Pass_BaseTexture(s);
1379 RSurfShader_Wall_Pass_BaseLightmap(s);
1382 if (s->currenttexture->glowtexture)
1383 RSurfShader_Wall_Pass_Glow(s);
1394 RSurfShader_Wall_Pass_BaseTexture(s);
1397 RSurfShader_Wall_Pass_BaseLightmap(s);
1400 if (s->dlightframe == r_framecount)
1401 RSurfShader_Wall_Pass_Light(s);
1404 if (s->currenttexture->glowtexture)
1405 RSurfShader_Wall_Pass_Glow(s);
1414 static int RSurfShader_Wall_Fog(int stage, msurface_t *s)
1416 if (stage == 0 && fogenabled)
1418 RSurfShader_Wall_Pass_Fog(s);
1426 =============================================================
1430 =============================================================
1433 static void RSurf_Callback(void *data, void *junk)
1435 ((msurface_t *)data)->visframe = r_framecount;
1438 static void R_SolidWorldNode (void)
1440 if (r_viewleaf->contents != CONTENTS_SOLID)
1443 mportal_t *p, *pstack[8192];
1444 msurface_t *surf, **mark, **endmark;
1447 // LordHavoc: portal-passage worldnode; follows portals leading
1448 // outward from viewleaf, if a portal leads offscreen it is not
1449 // followed, in indoor maps this can often cull a great deal of
1450 // geometry away when pvs data is not present (useful with pvs as well)
1453 leaf->worldnodeframe = r_framecount;
1458 leaf->visframe = r_framecount;
1460 if (leaf->nummarksurfaces)
1462 mark = leaf->firstmarksurface;
1463 endmark = mark + leaf->nummarksurfaces;
1469 // make sure surfaces are only processed once
1470 if (surf->worldnodeframe == r_framecount)
1472 surf->worldnodeframe = r_framecount;
1473 if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
1475 if (surf->flags & SURF_PLANEBACK)
1477 VectorNegate(surf->plane->normal, plane.normal);
1478 plane.dist = -surf->plane->dist;
1479 R_Clip_AddPolygon((float *)surf->poly_verts, surf->poly_numverts, sizeof(float[3]), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
1484 if (!(surf->flags & SURF_PLANEBACK))
1485 R_Clip_AddPolygon((float *)surf->poly_verts, surf->poly_numverts, sizeof(float[3]), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane);
1488 while (mark < endmark);
1495 // make sure surfaces are only processed once
1496 if (surf->worldnodeframe == r_framecount)
1498 surf->worldnodeframe = r_framecount;
1499 if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
1501 if (surf->flags & SURF_PLANEBACK)
1502 surf->visframe = r_framecount;
1506 if (!(surf->flags & SURF_PLANEBACK))
1507 surf->visframe = r_framecount;
1510 while (mark < endmark);
1514 // follow portals into other leafs
1516 for (;p;p = p->next)
1518 if (DotProduct(r_origin, p->plane.normal) < p->plane.dist)
1521 if (leaf->worldnodeframe != r_framecount)
1523 leaf->worldnodeframe = r_framecount;
1524 if (leaf->contents != CONTENTS_SOLID)
1526 if (R_NotCulledBox(leaf->mins, leaf->maxs))
1528 p->visframe = r_framecount;
1529 pstack[portalstack++] = p;
1533 p = pstack[--portalstack];
1545 mnode_t *nodestack[8192], *node = cl.worldmodel->nodes;
1546 int nodestackpos = 0;
1547 // LordHavoc: recursive descending worldnode; if portals are not
1548 // available, this is a good last resort, can cull large amounts of
1549 // geometry, but is more time consuming than portal-passage and renders
1550 // things behind walls
1553 if (R_NotCulledBox(node->mins, node->maxs))
1555 if (node->numsurfaces)
1559 msurface_t *surf = cl.worldmodel->surfaces + node->firstsurface, *surfend = surf + node->numsurfaces;
1561 if (PlaneDiff (r_origin, node->plane) < 0)
1563 for (;surf < surfend;surf++)
1565 if (surf->flags & SURF_PLANEBACK)
1567 VectorNegate(surf->plane->normal, plane.normal);
1568 plane.dist = -surf->plane->dist;
1569 R_Clip_AddPolygon((float *)surf->poly_verts, surf->poly_numverts, sizeof(float[3]), surf->flags & SURF_CLIPSOLID, RSurf_Callback, surf, NULL, &plane);
1575 for (;surf < surfend;surf++)
1577 if (!(surf->flags & SURF_PLANEBACK))
1578 R_Clip_AddPolygon((float *)surf->poly_verts, surf->poly_numverts, sizeof(float[3]), surf->flags & SURF_CLIPSOLID, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane);
1584 msurface_t *surf = cl.worldmodel->surfaces + node->firstsurface, *surfend = surf + node->numsurfaces;
1585 if (PlaneDiff (r_origin, node->plane) < 0)
1587 for (;surf < surfend;surf++)
1589 if (surf->flags & SURF_PLANEBACK)
1590 surf->visframe = r_framecount;
1595 for (;surf < surfend;surf++)
1597 if (!(surf->flags & SURF_PLANEBACK))
1598 surf->visframe = r_framecount;
1604 // recurse down the children
1605 if (node->children[0]->contents >= 0)
1607 if (node->children[1]->contents >= 0)
1609 if (nodestackpos < 8192)
1610 nodestack[nodestackpos++] = node->children[1];
1611 node = node->children[0];
1615 ((mleaf_t *)node->children[1])->visframe = r_framecount;
1616 node = node->children[0];
1621 ((mleaf_t *)node->children[0])->visframe = r_framecount;
1622 if (node->children[1]->contents >= 0)
1624 node = node->children[1];
1627 else if (nodestackpos > 0)
1629 ((mleaf_t *)node->children[1])->visframe = r_framecount;
1630 node = nodestack[--nodestackpos];
1635 else if (nodestackpos > 0)
1637 node = nodestack[--nodestackpos];
1643 static int r_portalframecount = 0;
1645 static void R_PVSWorldNode()
1648 mportal_t *p, *pstack[8192];
1649 msurface_t *surf, **mark, **endmark;
1654 worldvis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
1657 leaf->worldnodeframe = r_framecount;
1662 leaf->visframe = r_framecount;
1664 if (leaf->nummarksurfaces)
1666 mark = leaf->firstmarksurface;
1667 endmark = mark + leaf->nummarksurfaces;
1673 // make sure surfaces are only processed once
1674 if (surf->worldnodeframe == r_framecount)
1676 surf->worldnodeframe = r_framecount;
1677 if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
1679 if (surf->flags & SURF_PLANEBACK)
1681 VectorNegate(surf->plane->normal, plane.normal);
1682 plane.dist = -surf->plane->dist;
1683 R_Clip_AddPolygon((float *)surf->poly_verts, surf->poly_numverts, sizeof(float[3]), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
1688 if (!(surf->flags & SURF_PLANEBACK))
1689 R_Clip_AddPolygon((float *)surf->poly_verts, surf->poly_numverts, sizeof(float[3]), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, (tinyplane_t *)surf->plane);
1692 while (mark < endmark);
1699 // make sure surfaces are only processed once
1700 if (surf->worldnodeframe == r_framecount)
1702 surf->worldnodeframe = r_framecount;
1703 if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
1705 if (surf->flags & SURF_PLANEBACK)
1706 surf->visframe = r_framecount;
1710 if (!(surf->flags & SURF_PLANEBACK))
1711 surf->visframe = r_framecount;
1714 while (mark < endmark);
1718 // follow portals into other leafs
1719 for (p = leaf->portals;p;p = p->next)
1721 if (DotProduct(r_origin, p->plane.normal) < p->plane.dist)
1724 if (leaf->worldnodeframe != r_framecount)
1726 leaf->worldnodeframe = r_framecount;
1727 if (leaf->contents != CONTENTS_SOLID)
1729 i = (leaf - cl.worldmodel->leafs) - 1;
1730 if (worldvis[i>>3] & (1<<(i&7)))
1732 if (R_NotCulledBox(leaf->mins, leaf->maxs))
1734 pstack[portalstack++] = p;
1738 p = pstack[--portalstack];
1750 Cshader_t Cshader_wall_vertex = {{NULL, RSurfShader_Wall_Vertex, RSurfShader_Wall_Fog}, NULL};
1751 Cshader_t Cshader_wall_lightmap = {{NULL, RSurfShader_Wall_Lightmap, RSurfShader_Wall_Fog}, NULL};
1752 Cshader_t Cshader_wall_fullbright = {{NULL, RSurfShader_Wall_Fullbright, RSurfShader_Wall_Fog}, NULL};
1753 Cshader_t Cshader_water = {{NULL, RSurfShader_Water, NULL}, NULL};
1754 Cshader_t Cshader_sky = {{RSurfShader_Sky, NULL, NULL}, NULL};
1756 int Cshader_count = 5;
1757 Cshader_t *Cshaders[5] =
1759 &Cshader_wall_vertex,
1760 &Cshader_wall_lightmap,
1761 &Cshader_wall_fullbright,
1766 void R_PrepareSurfaces(void)
1773 for (i = 0;i < Cshader_count;i++)
1774 Cshaders[i]->chain = NULL;
1776 model = currentrenderentity->model;
1778 for (i = 0;i < model->nummodelsurfaces;i++)
1780 surf = model->modelsortedsurfaces[i];
1781 if (surf->visframe == r_framecount)
1783 if (surf->insertframe != r_framecount)
1785 surf->insertframe = r_framecount;
1787 // manually inlined R_TextureAnimation
1788 //t = R_TextureAnimation(surf->texinfo->texture);
1789 t = surf->texinfo->texture;
1790 if (t->alternate_anims != NULL && currentrenderentity->frame)
1791 t = t->alternate_anims;
1792 if (t->anim_total >= 2)
1793 t = t->anim_frames[(int)(cl.time * 5.0f) % t->anim_total];
1794 surf->currenttexture = t;
1797 surf->chain = surf->shader->chain;
1798 surf->shader->chain = surf;
1803 void R_DrawSurfaces (int type)
1809 for (i = 0;i < Cshader_count;i++)
1811 shader = Cshaders[i];
1812 if (shader->chain && shader->shaderfunc[type])
1813 for (stage = 0;stage < 1000;stage++)
1814 for (surf = shader->chain;surf;surf = surf->chain)
1815 if (shader->shaderfunc[type](stage, surf))
1821 void R_DrawSurfacesAll (void)
1823 R_DrawSurfaces(SHADERSTAGE_SKY);
1824 R_DrawSurfaces(SHADERSTAGE_NORMAL);
1825 R_DrawSurfaces(SHADERSTAGE_FOG);
1828 static float portalpointbuffer[256][3];
1830 void R_DrawPortals(void)
1833 // mleaf_t *leaf, *endleaf;
1834 mportal_t *portal, *endportal;
1835 mvertex_t *point/*, *endpoint*/;
1837 drawportals = r_drawportals.integer;
1838 if (drawportals < 1)
1841 leaf = cl.worldmodel->leafs;
1842 endleaf = leaf + cl.worldmodel->numleafs;
1843 for (;leaf < endleaf;leaf++)
1845 if (leaf->visframe == r_framecount && leaf->portals)
1847 i = leaf - cl.worldmodel->leafs;
1848 r = (i & 0x0007) << 5;
1849 g = (i & 0x0038) << 2;
1850 b = (i & 0x01C0) >> 1;
1851 portal = leaf->portals;
1854 transpolybegin(0, 0, 0, TPOLYTYPE_ALPHA);
1855 point = portal->points + portal->numpoints - 1;
1856 endpoint = portal->points;
1857 for (;point >= endpoint;point--)
1858 transpolyvertub(point->position[0], point->position[1], point->position[2], 0, 0, r, g, b, 32);
1860 portal = portal->next;
1865 memset(&m, 0, sizeof(m));
1866 m.transparent = true;
1867 m.blendfunc1 = GL_SRC_ALPHA;
1868 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1869 m.vertex = &portalpointbuffer[0][0];
1870 m.vertexstep = sizeof(float[3]);
1872 for (portal = cl.worldmodel->portals, endportal = portal + cl.worldmodel->numportals;portal < endportal;portal++)
1874 if (portal->visframe == r_portalframecount)
1876 if (portal->numpoints <= 256)
1878 i = portal - cl.worldmodel->portals;
1879 m.cr = ((i & 0x0007) >> 0) * (1.0f / 7.0f);
1880 m.cg = ((i & 0x0038) >> 3) * (1.0f / 7.0f);
1881 m.cb = ((i & 0x01C0) >> 6) * (1.0f / 7.0f);
1882 point = portal->points;
1883 if (PlaneDiff(r_origin, (&portal->plane)) > 0)
1885 for (i = portal->numpoints - 1;i >= 0;i--)
1886 VectorCopy(point[i].position, portalpointbuffer[i]);
1890 for (i = 0;i < portal->numpoints;i++)
1891 VectorCopy(point[i].position, portalpointbuffer[i]);
1893 R_Mesh_DrawPolygon(&m, portal->numpoints);
1899 void R_SetupForBModelRendering(void)
1906 // because bmodels can be reused, we have to decide which things to render
1907 // from scratch every time
1909 model = currentrenderentity->model;
1911 softwaretransformforentity (currentrenderentity);
1912 softwareuntransform(r_origin, modelorg);
1914 for (i = 0;i < model->nummodelsurfaces;i++)
1916 s = model->modelsortedsurfaces[i];
1917 if (((s->flags & SURF_PLANEBACK) == 0) == (PlaneDiff(modelorg, s->plane) >= 0))
1918 s->visframe = r_framecount;
1921 s->worldnodeframe = -1;
1923 s->dlightframe = -1;
1924 s->insertframe = -1;
1928 void R_SetupForWorldRendering(void)
1930 // there is only one instance of the world, but it can be rendered in
1933 currentrenderentity = &cl_entities[0].render;
1934 softwaretransformidentity();
1937 static void R_SurfMarkLights (void)
1942 if (r_dynamic.integer)
1945 if (!r_vertexsurfaces.integer)
1947 for (i = 0;i < currentrenderentity->model->nummodelsurfaces;i++)
1949 s = currentrenderentity->model->modelsortedsurfaces[i];
1950 if (s->visframe == r_framecount && s->lightmaptexture != NULL)
1952 if (s->cached_dlight
1953 || s->cached_ambient != r_ambient.value
1954 || s->cached_lightscalebit != lightscalebit)
1955 R_BuildLightMap(s, false); // base lighting changed
1956 else if (r_dynamic.integer)
1958 if (s->styles[0] != 255 && (d_lightstylevalue[s->styles[0]] != s->cached_light[0]
1959 || (s->styles[1] != 255 && (d_lightstylevalue[s->styles[1]] != s->cached_light[1]
1960 || (s->styles[2] != 255 && (d_lightstylevalue[s->styles[2]] != s->cached_light[2]
1961 || (s->styles[3] != 255 && (d_lightstylevalue[s->styles[3]] != s->cached_light[3]))))))))
1962 //if (s->cached_light[0] != d_lightstylevalue[s->styles[0]]
1963 // || s->cached_light[1] != d_lightstylevalue[s->styles[1]]
1964 // || s->cached_light[2] != d_lightstylevalue[s->styles[2]]
1965 // || s->cached_light[3] != d_lightstylevalue[s->styles[3]])
1966 R_BuildLightMap(s, false); // base lighting changed
1967 else if (s->dlightframe == r_framecount && r_dlightmap.integer)
1968 R_BuildLightMap(s, true); // only dlights
1975 void R_MarkWorldLights(void)
1977 R_SetupForWorldRendering();
1986 void R_DrawWorld (void)
1988 R_SetupForWorldRendering();
1990 if (r_viewleaf->contents == CONTENTS_SOLID || r_novis.integer || r_viewleaf->compressed_vis == NULL)
1991 R_SolidWorldNode ();
2001 void R_DrawBrushModelSky (void)
2003 R_SetupForBModelRendering();
2005 R_PrepareSurfaces();
2006 R_DrawSurfaces(SHADERSTAGE_SKY);
2009 void R_DrawBrushModelNormal (void)
2013 // have to flush queue because of possible lightmap reuse
2016 R_SetupForBModelRendering();
2020 R_PrepareSurfaces();
2022 if (!skyrendermasked)
2023 R_DrawSurfaces(SHADERSTAGE_SKY);
2024 R_DrawSurfaces(SHADERSTAGE_NORMAL);
2025 R_DrawSurfaces(SHADERSTAGE_FOG);