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 = 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_SRC_ALPHA;
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);
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 = 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 = 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);
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 (currentrenderentity != &cl_entities[0].render && (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)
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 (currentrenderentity != &cl_entities[0].render && (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_Light(msurface_t *s)
1025 float diff[3], ifog;
1030 memset(&m, 0, sizeof(m));
1031 if (currentrenderentity->effects & EF_ADDITIVE)
1032 m.transparent = true;
1033 else if (currentrenderentity != &cl_entities[0].render && (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1))
1034 m.transparent = true;
1036 m.transparent = false;
1037 m.blendfunc1 = GL_SRC_ALPHA;
1038 m.blendfunc2 = GL_ONE;
1039 m.numtriangles = s->mesh.numtriangles;
1040 m.numverts = s->mesh.numverts;
1041 m.index = s->mesh.index;
1042 m.vertex = &svert[0].v[0];
1043 m.vertexstep = sizeof(surfvert_t);
1044 m.color = &svert[0].c[0];
1045 m.colorstep = sizeof(surfvert_t);
1046 m.tex[0] = R_GetTexture(s->currenttexture->texture);
1047 m.texcoords[0] = &s->mesh.vertex->st[0];
1048 m.texcoordstep[0] = sizeof(surfvertex_t);
1049 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
1051 softwaretransform(v->v, sv->v);
1055 sv->c[3] = currentrenderentity->alpha;
1057 if (RSurf_Light(s->dlightbits, m.numverts))
1061 for (i = 0, sv = svert;i < m.numverts;i++, sv++)
1063 VectorSubtract(sv->v, r_origin, diff);
1064 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
1074 static void RSurfShader_Wall_Pass_Glow(msurface_t *s)
1077 float diff[3], ifog;
1082 memset(&m, 0, sizeof(m));
1083 if (currentrenderentity->effects & EF_ADDITIVE)
1084 m.transparent = true;
1085 else if (currentrenderentity != &cl_entities[0].render && (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1))
1086 m.transparent = true;
1088 m.transparent = false;
1089 m.blendfunc1 = GL_SRC_ALPHA;
1090 m.blendfunc2 = GL_ONE;
1091 m.numtriangles = s->mesh.numtriangles;
1092 m.numverts = s->mesh.numverts;
1093 m.index = s->mesh.index;
1097 m.ca = currentrenderentity->alpha;
1098 m.tex[0] = R_GetTexture(s->currenttexture->glowtexture);
1099 m.texcoords[0] = &s->mesh.vertex->st[0];
1100 m.texcoordstep[0] = sizeof(surfvertex_t);
1103 m.color = &svert[0].c[0];
1104 m.colorstep = sizeof(surfvert_t);
1105 if (softwaretransform_complexity)
1107 m.vertex = &svert[0].v[0];
1108 m.vertexstep = sizeof(surfvert_t);
1109 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
1111 softwaretransform(v->v, sv->v);
1112 VectorSubtract(sv->v, r_origin, diff);
1113 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
1114 sv->c[0] = m.cr * ifog;
1115 sv->c[1] = m.cg * ifog;
1116 sv->c[2] = m.cb * ifog;
1122 m.vertex = &s->mesh.vertex->v[0];
1123 m.vertexstep = sizeof(surfvertex_t);
1124 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
1126 VectorSubtract(v->v, r_origin, diff);
1127 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
1128 sv->c[0] = m.cr * ifog;
1129 sv->c[1] = m.cg * ifog;
1130 sv->c[2] = m.cb * ifog;
1137 if (softwaretransform_complexity)
1139 m.vertex = &svert[0].v[0];
1140 m.vertexstep = sizeof(surfvert_t);
1141 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
1142 softwaretransform(v->v, sv->v);
1146 m.vertex = &s->mesh.vertex->v[0];
1147 m.vertexstep = sizeof(surfvertex_t);
1153 static void RSurfShader_Wall_Pass_Fog(msurface_t *s)
1161 memset(&m, 0, sizeof(m));
1162 if (currentrenderentity->effects & EF_ADDITIVE)
1163 m.transparent = true;
1164 else if (currentrenderentity != &cl_entities[0].render && (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1))
1165 m.transparent = true;
1167 m.transparent = false;
1168 m.blendfunc1 = GL_SRC_ALPHA;
1169 m.blendfunc2 = GL_ONE;
1170 m.numtriangles = s->mesh.numtriangles;
1171 m.numverts = s->mesh.numverts;
1172 m.index = s->mesh.index;
1173 m.color = &svert[0].c[0];
1174 m.colorstep = sizeof(surfvert_t);
1175 m.tex[0] = R_GetTexture(s->currenttexture->fogtexture);
1176 m.texcoords[0] = &s->mesh.vertex->st[0];
1177 m.texcoordstep[0] = sizeof(surfvertex_t);
1178 if (softwaretransform_complexity)
1180 m.vertex = &svert[0].v[0];
1181 m.vertexstep = sizeof(surfvert_t);
1182 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
1184 softwaretransform(v->v, sv->v);
1185 VectorSubtract(sv->v, r_origin, diff);
1186 sv->c[0] = fogcolor[0];
1187 sv->c[1] = fogcolor[1];
1188 sv->c[2] = fogcolor[2];
1189 sv->c[3] = currentrenderentity->alpha * exp(fogdensity/DotProduct(diff,diff));
1194 m.vertex = &s->mesh.vertex->v[0];
1195 m.vertexstep = sizeof(surfvertex_t);
1196 for (i = 0, sv = svert, v = s->mesh.vertex;i < m.numverts;i++, sv++, v++)
1198 VectorSubtract(v->v, r_origin, diff);
1199 sv->c[0] = fogcolor[0];
1200 sv->c[1] = fogcolor[1];
1201 sv->c[2] = fogcolor[2];
1202 sv->c[3] = currentrenderentity->alpha * exp(fogdensity/DotProduct(diff,diff));
1208 static int RSurfShader_Wall_Vertex(int stage, msurface_t *s)
1213 RSurfShader_Wall_Pass_BaseVertex(s);
1216 if (s->currenttexture->glowtexture)
1217 RSurfShader_Wall_Pass_Glow(s);
1224 static int RSurfShader_Wall_Lightmap(int stage, msurface_t *s)
1226 if (r_vertexsurfaces.integer)
1231 RSurfShader_Wall_Pass_BaseVertex(s);
1234 if (s->currenttexture->glowtexture)
1235 RSurfShader_Wall_Pass_Glow(s);
1241 else if (r_multitexture.integer)
1243 if (r_dlightmap.integer)
1248 RSurfShader_Wall_Pass_BaseMTex(s);
1251 if (s->currenttexture->glowtexture)
1252 RSurfShader_Wall_Pass_Glow(s);
1263 RSurfShader_Wall_Pass_BaseMTex(s);
1266 if (s->dlightframe == r_framecount)
1267 RSurfShader_Wall_Pass_Light(s);
1270 if (s->currenttexture->glowtexture)
1271 RSurfShader_Wall_Pass_Glow(s);
1278 else if (currentrenderentity != &cl_entities[0].render && (s->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1 || currentrenderentity->effects & EF_ADDITIVE))
1283 RSurfShader_Wall_Pass_BaseVertex(s);
1286 if (s->currenttexture->glowtexture)
1287 RSurfShader_Wall_Pass_Glow(s);
1295 if (r_dlightmap.integer)
1300 RSurfShader_Wall_Pass_BaseTexture(s);
1303 RSurfShader_Wall_Pass_BaseLightmap(s);
1306 if (s->currenttexture->glowtexture)
1307 RSurfShader_Wall_Pass_Glow(s);
1318 RSurfShader_Wall_Pass_BaseTexture(s);
1321 RSurfShader_Wall_Pass_BaseLightmap(s);
1324 if (s->dlightframe == r_framecount)
1325 RSurfShader_Wall_Pass_Light(s);
1328 if (s->currenttexture->glowtexture)
1329 RSurfShader_Wall_Pass_Glow(s);
1338 static int RSurfShader_Wall_Fog(int stage, msurface_t *s)
1340 if (stage == 0 && fogenabled)
1342 RSurfShader_Wall_Pass_Fog(s);
1350 =============================================================
1354 =============================================================
1357 static void RSurf_Callback(void *data, void *junk)
1359 ((msurface_t *)data)->visframe = r_framecount;
1362 static void R_SolidWorldNode (void)
1364 if (r_viewleaf->contents != CONTENTS_SOLID)
1367 mportal_t *p, *pstack[8192];
1368 msurface_t *surf, **mark, **endmark;
1371 // LordHavoc: portal-passage worldnode; follows portals leading
1372 // outward from viewleaf, if a portal leads offscreen it is not
1373 // followed, in indoor maps this can often cull a great deal of
1374 // geometry away when pvs data is not present (useful with pvs as well)
1377 leaf->worldnodeframe = r_framecount;
1382 leaf->visframe = r_framecount;
1384 if (leaf->nummarksurfaces)
1386 mark = leaf->firstmarksurface;
1387 endmark = mark + leaf->nummarksurfaces;
1393 // make sure surfaces are only processed once
1394 if (surf->worldnodeframe == r_framecount)
1396 surf->worldnodeframe = r_framecount;
1397 if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
1399 if (surf->flags & SURF_PLANEBACK)
1401 VectorNegate(surf->plane->normal, plane.normal);
1402 plane.dist = -surf->plane->dist;
1403 R_Clip_AddPolygon((float *)surf->poly_verts, surf->poly_numverts, sizeof(float[3]), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
1408 if (!(surf->flags & SURF_PLANEBACK))
1409 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);
1412 while (mark < endmark);
1419 // make sure surfaces are only processed once
1420 if (surf->worldnodeframe == r_framecount)
1422 surf->worldnodeframe = r_framecount;
1423 if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
1425 if (surf->flags & SURF_PLANEBACK)
1426 surf->visframe = r_framecount;
1430 if (!(surf->flags & SURF_PLANEBACK))
1431 surf->visframe = r_framecount;
1434 while (mark < endmark);
1438 // follow portals into other leafs
1440 for (;p;p = p->next)
1442 if (DotProduct(r_origin, p->plane.normal) < p->plane.dist)
1445 if (leaf->worldnodeframe != r_framecount)
1447 leaf->worldnodeframe = r_framecount;
1448 if (leaf->contents != CONTENTS_SOLID)
1450 if (R_NotCulledBox(leaf->mins, leaf->maxs))
1452 p->visframe = r_framecount;
1453 pstack[portalstack++] = p;
1457 p = pstack[--portalstack];
1469 mnode_t *nodestack[8192], *node = cl.worldmodel->nodes;
1470 int nodestackpos = 0;
1471 // LordHavoc: recursive descending worldnode; if portals are not
1472 // available, this is a good last resort, can cull large amounts of
1473 // geometry, but is more time consuming than portal-passage and renders
1474 // things behind walls
1477 if (R_NotCulledBox(node->mins, node->maxs))
1479 if (node->numsurfaces)
1483 msurface_t *surf = cl.worldmodel->surfaces + node->firstsurface, *surfend = surf + node->numsurfaces;
1485 if (PlaneDiff (r_origin, node->plane) < 0)
1487 for (;surf < surfend;surf++)
1489 if (surf->flags & SURF_PLANEBACK)
1491 VectorNegate(surf->plane->normal, plane.normal);
1492 plane.dist = -surf->plane->dist;
1493 R_Clip_AddPolygon((float *)surf->poly_verts, surf->poly_numverts, sizeof(float[3]), surf->flags & SURF_CLIPSOLID, RSurf_Callback, surf, NULL, &plane);
1499 for (;surf < surfend;surf++)
1501 if (!(surf->flags & SURF_PLANEBACK))
1502 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);
1508 msurface_t *surf = cl.worldmodel->surfaces + node->firstsurface, *surfend = surf + node->numsurfaces;
1509 if (PlaneDiff (r_origin, node->plane) < 0)
1511 for (;surf < surfend;surf++)
1513 if (surf->flags & SURF_PLANEBACK)
1514 surf->visframe = r_framecount;
1519 for (;surf < surfend;surf++)
1521 if (!(surf->flags & SURF_PLANEBACK))
1522 surf->visframe = r_framecount;
1528 // recurse down the children
1529 if (node->children[0]->contents >= 0)
1531 if (node->children[1]->contents >= 0)
1533 if (nodestackpos < 8192)
1534 nodestack[nodestackpos++] = node->children[1];
1535 node = node->children[0];
1539 ((mleaf_t *)node->children[1])->visframe = r_framecount;
1540 node = node->children[0];
1545 ((mleaf_t *)node->children[0])->visframe = r_framecount;
1546 if (node->children[1]->contents >= 0)
1548 node = node->children[1];
1551 else if (nodestackpos > 0)
1553 ((mleaf_t *)node->children[1])->visframe = r_framecount;
1554 node = nodestack[--nodestackpos];
1559 else if (nodestackpos > 0)
1561 node = nodestack[--nodestackpos];
1567 static int r_portalframecount = 0;
1569 static void R_PVSWorldNode()
1572 mportal_t *p, *pstack[8192];
1573 msurface_t *surf, **mark, **endmark;
1578 worldvis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
1581 leaf->worldnodeframe = r_framecount;
1586 leaf->visframe = r_framecount;
1588 if (leaf->nummarksurfaces)
1590 mark = leaf->firstmarksurface;
1591 endmark = mark + leaf->nummarksurfaces;
1597 // make sure surfaces are only processed once
1598 if (surf->worldnodeframe == r_framecount)
1600 surf->worldnodeframe = r_framecount;
1601 if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
1603 if (surf->flags & SURF_PLANEBACK)
1605 VectorNegate(surf->plane->normal, plane.normal);
1606 plane.dist = -surf->plane->dist;
1607 R_Clip_AddPolygon((float *)surf->poly_verts, surf->poly_numverts, sizeof(float[3]), (surf->flags & SURF_CLIPSOLID) != 0, RSurf_Callback, surf, NULL, &plane);
1612 if (!(surf->flags & SURF_PLANEBACK))
1613 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);
1616 while (mark < endmark);
1623 // make sure surfaces are only processed once
1624 if (surf->worldnodeframe == r_framecount)
1626 surf->worldnodeframe = r_framecount;
1627 if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
1629 if (surf->flags & SURF_PLANEBACK)
1630 surf->visframe = r_framecount;
1634 if (!(surf->flags & SURF_PLANEBACK))
1635 surf->visframe = r_framecount;
1638 while (mark < endmark);
1642 // follow portals into other leafs
1643 for (p = leaf->portals;p;p = p->next)
1645 if (DotProduct(r_origin, p->plane.normal) < p->plane.dist)
1648 if (leaf->worldnodeframe != r_framecount)
1650 leaf->worldnodeframe = r_framecount;
1651 if (leaf->contents != CONTENTS_SOLID)
1653 i = (leaf - cl.worldmodel->leafs) - 1;
1654 if (worldvis[i>>3] & (1<<(i&7)))
1656 if (R_NotCulledBox(leaf->mins, leaf->maxs))
1658 pstack[portalstack++] = p;
1662 p = pstack[--portalstack];
1674 Cshader_t Cshader_wall_vertex = {{NULL, RSurfShader_Wall_Vertex, RSurfShader_Wall_Fog}, NULL};
1675 Cshader_t Cshader_wall_lightmap = {{NULL, RSurfShader_Wall_Lightmap, RSurfShader_Wall_Fog}, NULL};
1676 Cshader_t Cshader_water = {{NULL, RSurfShader_Water, NULL}, NULL};
1677 Cshader_t Cshader_sky = {{RSurfShader_Sky, NULL, NULL}, NULL};
1679 int Cshader_count = 4;
1680 Cshader_t *Cshaders[4] =
1682 &Cshader_wall_vertex,
1683 &Cshader_wall_lightmap,
1688 void R_PrepareSurfaces(void)
1695 for (i = 0;i < Cshader_count;i++)
1696 Cshaders[i]->chain = NULL;
1698 model = currentrenderentity->model;
1700 for (i = 0;i < model->nummodelsurfaces;i++)
1702 surf = model->modelsortedsurfaces[i];
1703 if (surf->visframe == r_framecount)
1705 if (surf->insertframe != r_framecount)
1707 surf->insertframe = r_framecount;
1709 // manually inlined R_TextureAnimation
1710 //t = R_TextureAnimation(surf->texinfo->texture);
1711 t = surf->texinfo->texture;
1712 if (t->alternate_anims != NULL && currentrenderentity->frame)
1713 t = t->alternate_anims;
1714 if (t->anim_total >= 2)
1715 t = t->anim_frames[(int)(cl.time * 5.0f) % t->anim_total];
1716 surf->currenttexture = t;
1719 surf->chain = surf->shader->chain;
1720 surf->shader->chain = surf;
1725 void R_DrawSurfaces (int type)
1731 for (i = 0;i < Cshader_count;i++)
1733 shader = Cshaders[i];
1734 if (shader->chain && shader->shaderfunc[type])
1735 for (stage = 0;stage < 1000;stage++)
1736 for (surf = shader->chain;surf;surf = surf->chain)
1737 if (shader->shaderfunc[type](stage, surf))
1743 void R_DrawSurfacesAll (void)
1745 R_DrawSurfaces(SHADERSTAGE_SKY);
1746 R_DrawSurfaces(SHADERSTAGE_NORMAL);
1747 R_DrawSurfaces(SHADERSTAGE_FOG);
1750 static float portalpointbuffer[256][3];
1752 void R_DrawPortals(void)
1755 // mleaf_t *leaf, *endleaf;
1756 mportal_t *portal, *endportal;
1757 mvertex_t *point/*, *endpoint*/;
1759 drawportals = r_drawportals.integer;
1760 if (drawportals < 1)
1763 leaf = cl.worldmodel->leafs;
1764 endleaf = leaf + cl.worldmodel->numleafs;
1765 for (;leaf < endleaf;leaf++)
1767 if (leaf->visframe == r_framecount && leaf->portals)
1769 i = leaf - cl.worldmodel->leafs;
1770 r = (i & 0x0007) << 5;
1771 g = (i & 0x0038) << 2;
1772 b = (i & 0x01C0) >> 1;
1773 portal = leaf->portals;
1776 transpolybegin(0, 0, 0, TPOLYTYPE_ALPHA);
1777 point = portal->points + portal->numpoints - 1;
1778 endpoint = portal->points;
1779 for (;point >= endpoint;point--)
1780 transpolyvertub(point->position[0], point->position[1], point->position[2], 0, 0, r, g, b, 32);
1782 portal = portal->next;
1787 memset(&m, 0, sizeof(m));
1788 m.transparent = true;
1789 m.blendfunc1 = GL_SRC_ALPHA;
1790 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1791 m.vertex = &portalpointbuffer[0][0];
1792 m.vertexstep = sizeof(float[3]);
1794 for (portal = cl.worldmodel->portals, endportal = portal + cl.worldmodel->numportals;portal < endportal;portal++)
1796 if (portal->visframe == r_portalframecount)
1798 if (portal->numpoints <= 256)
1800 i = portal - cl.worldmodel->portals;
1801 m.cr = ((i & 0x0007) >> 0) * (1.0f / 7.0f);
1802 m.cg = ((i & 0x0038) >> 3) * (1.0f / 7.0f);
1803 m.cb = ((i & 0x01C0) >> 6) * (1.0f / 7.0f);
1804 point = portal->points;
1805 if (PlaneDiff(r_origin, (&portal->plane)) > 0)
1807 for (i = portal->numpoints - 1;i >= 0;i--)
1808 VectorCopy(point[i].position, portalpointbuffer[i]);
1812 for (i = 0;i < portal->numpoints;i++)
1813 VectorCopy(point[i].position, portalpointbuffer[i]);
1815 R_Mesh_DrawPolygon(&m, portal->numpoints);
1821 void R_SetupForBModelRendering(void)
1828 // because bmodels can be reused, we have to decide which things to render
1829 // from scratch every time
1831 model = currentrenderentity->model;
1833 softwaretransformforentity (currentrenderentity);
1834 softwareuntransform(r_origin, modelorg);
1836 for (i = 0;i < model->nummodelsurfaces;i++)
1838 s = model->modelsortedsurfaces[i];
1839 if (((s->flags & SURF_PLANEBACK) == 0) == (PlaneDiff(modelorg, s->plane) >= 0))
1840 s->visframe = r_framecount;
1843 s->worldnodeframe = -1;
1845 s->dlightframe = -1;
1846 s->insertframe = -1;
1850 void R_SetupForWorldRendering(void)
1852 // there is only one instance of the world, but it can be rendered in
1855 currentrenderentity = &cl_entities[0].render;
1856 softwaretransformidentity();
1859 static void R_SurfMarkLights (void)
1864 if (r_dynamic.integer)
1867 if (!r_vertexsurfaces.integer)
1869 for (i = 0;i < currentrenderentity->model->nummodelsurfaces;i++)
1871 s = currentrenderentity->model->modelsortedsurfaces[i];
1872 if (s->visframe == r_framecount && s->lightmaptexture != NULL)
1874 if (s->cached_dlight
1875 || s->cached_ambient != r_ambient.value
1876 || s->cached_lightscalebit != lightscalebit)
1877 R_BuildLightMap(s, false); // base lighting changed
1878 else if (r_dynamic.integer)
1880 if (s->styles[0] != 255 && (d_lightstylevalue[s->styles[0]] != s->cached_light[0]
1881 || (s->styles[1] != 255 && (d_lightstylevalue[s->styles[1]] != s->cached_light[1]
1882 || (s->styles[2] != 255 && (d_lightstylevalue[s->styles[2]] != s->cached_light[2]
1883 || (s->styles[3] != 255 && (d_lightstylevalue[s->styles[3]] != s->cached_light[3]))))))))
1884 //if (s->cached_light[0] != d_lightstylevalue[s->styles[0]]
1885 // || s->cached_light[1] != d_lightstylevalue[s->styles[1]]
1886 // || s->cached_light[2] != d_lightstylevalue[s->styles[2]]
1887 // || s->cached_light[3] != d_lightstylevalue[s->styles[3]])
1888 R_BuildLightMap(s, false); // base lighting changed
1889 else if (s->dlightframe == r_framecount && r_dlightmap.integer)
1890 R_BuildLightMap(s, true); // only dlights
1897 void R_MarkWorldLights(void)
1899 R_SetupForWorldRendering();
1908 void R_DrawWorld (void)
1910 R_SetupForWorldRendering();
1912 if (r_viewleaf->contents == CONTENTS_SOLID || r_novis.integer || r_viewleaf->compressed_vis == NULL)
1913 R_SolidWorldNode ();
1923 void R_DrawBrushModelSky (void)
1925 R_SetupForBModelRendering();
1927 R_PrepareSurfaces();
1928 R_DrawSurfaces(SHADERSTAGE_SKY);
1931 void R_DrawBrushModelNormal (void)
1935 // have to flush queue because of possible lightmap reuse
1938 R_SetupForBModelRendering();
1942 R_PrepareSurfaces();
1944 if (!skyrendermasked)
1945 R_DrawSurfaces(SHADERSTAGE_SKY);
1946 R_DrawSurfaces(SHADERSTAGE_NORMAL);
1947 R_DrawSurfaces(SHADERSTAGE_FOG);