corrected spelling of alorgithm
[xonotic/darkplaces.git] / gl_rsurf.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
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.
8
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.
12
13 See the GNU General Public License for more details.
14
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.
18
19 */
20 // r_surf.c: surface-related refresh code
21
22 #include "quakedef.h"
23
24 #define MAX_LIGHTMAP_SIZE 256
25 #define USEMESHBUFFER 1
26
27 static unsigned int intblocklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*3]; // LordHavoc: *3 for colored lighting
28 static float floatblocklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*3]; // LordHavoc: *3 for colored lighting
29
30 static qbyte templight[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*4];
31
32 cvar_t r_ambient = {0, "r_ambient", "0"};
33 cvar_t r_vertexsurfaces = {0, "r_vertexsurfaces", "0"};
34 cvar_t r_dlightmap = {CVAR_SAVE, "r_dlightmap", "1"};
35 cvar_t r_drawportals = {0, "r_drawportals", "0"};
36 cvar_t r_testvis = {0, "r_testvis", "0"};
37 cvar_t r_floatbuildlightmap = {0, "r_floatbuildlightmap", "0"};
38
39 static int dlightdivtable[32768];
40
41 static int R_IntAddDynamicLights (msurface_t *surf)
42 {
43         int sdtable[256], lnum, td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, smax3, red, green, blue, lit, dist2, impacts, impactt, subtract;
44         unsigned int *bl;
45         float dist, impact[3], local[3];
46
47         // LordHavoc: use 64bit integer...  shame it's not very standardized...
48 #if _MSC_VER || __BORLANDC__
49         __int64     k;
50 #else
51         long long   k;
52 #endif
53
54         lit = false;
55
56         smax = (surf->extents[0] >> 4) + 1;
57         tmax = (surf->extents[1] >> 4) + 1;
58         smax3 = smax * 3;
59
60         for (lnum = 0; lnum < r_numdlights; lnum++)
61         {
62                 if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31))))
63                         continue;                                       // not lit by this light
64
65                 softwareuntransform(r_dlight[lnum].origin, local);
66                 dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
67
68                 // for comparisons to minimum acceptable light
69                 // compensate for LIGHTOFFSET
70                 maxdist = (int) r_dlight[lnum].cullradius2 + LIGHTOFFSET;
71
72                 dist2 = dist * dist;
73                 dist2 += LIGHTOFFSET;
74                 if (dist2 >= maxdist)
75                         continue;
76
77                 if (surf->plane->type < 3)
78                 {
79                         VectorCopy(local, impact);
80                         impact[surf->plane->type] -= dist;
81                 }
82                 else
83                 {
84                         impact[0] = local[0] - surf->plane->normal[0] * dist;
85                         impact[1] = local[1] - surf->plane->normal[1] * dist;
86                         impact[2] = local[2] - surf->plane->normal[2] * dist;
87                 }
88
89                 impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
90                 impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
91
92                 s = bound(0, impacts, smax * 16) - impacts;
93                 t = bound(0, impactt, tmax * 16) - impactt;
94                 i = s * s + t * t + dist2;
95                 if (i > maxdist)
96                         continue;
97
98                 // reduce calculations
99                 for (s = 0, i = impacts; s < smax; s++, i -= 16)
100                         sdtable[s] = i * i + dist2;
101
102                 maxdist3 = maxdist - dist2;
103
104                 // convert to 8.8 blocklights format
105                 red = r_dlight[lnum].light[0];
106                 green = r_dlight[lnum].light[1];
107                 blue = r_dlight[lnum].light[2];
108                 subtract = (int) (r_dlight[lnum].subtract * 4194304.0f);
109                 bl = intblocklights;
110
111                 i = impactt;
112                 for (t = 0;t < tmax;t++, i -= 16)
113                 {
114                         td = i * i;
115                         // make sure some part of it is visible on this line
116                         if (td < maxdist3)
117                         {
118                                 maxdist2 = maxdist - td;
119                                 for (s = 0;s < smax;s++)
120                                 {
121                                         if (sdtable[s] < maxdist2)
122                                         {
123                                                 k = dlightdivtable[(sdtable[s] + td) >> 7] - subtract;
124                                                 if (k > 0)
125                                                 {
126                                                         bl[0] += (red   * k) >> 7;
127                                                         bl[1] += (green * k) >> 7;
128                                                         bl[2] += (blue  * k) >> 7;
129                                                         lit = true;
130                                                 }
131                                         }
132                                         bl += 3;
133                                 }
134                         }
135                         else // skip line
136                                 bl += smax3;
137                 }
138         }
139         return lit;
140 }
141
142 static int R_FloatAddDynamicLights (msurface_t *surf)
143 {
144         int lnum, s, t, smax, tmax, smax3, lit, impacts, impactt;
145         float sdtable[256], *bl, k, dist, dist2, maxdist, maxdist2, maxdist3, td1, td, red, green, blue, impact[3], local[3], subtract;
146
147         lit = false;
148
149         smax = (surf->extents[0] >> 4) + 1;
150         tmax = (surf->extents[1] >> 4) + 1;
151         smax3 = smax * 3;
152
153         for (lnum = 0; lnum < r_numdlights; lnum++)
154         {
155                 if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31))))
156                         continue;                                       // not lit by this light
157
158                 softwareuntransform(r_dlight[lnum].origin, local);
159                 dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
160
161                 // for comparisons to minimum acceptable light
162                 // compensate for LIGHTOFFSET
163                 maxdist = (int) r_dlight[lnum].cullradius2 + LIGHTOFFSET;
164
165                 dist2 = dist * dist;
166                 dist2 += LIGHTOFFSET;
167                 if (dist2 >= maxdist)
168                         continue;
169
170                 if (surf->plane->type < 3)
171                 {
172                         VectorCopy(local, impact);
173                         impact[surf->plane->type] -= dist;
174                 }
175                 else
176                 {
177                         impact[0] = local[0] - surf->plane->normal[0] * dist;
178                         impact[1] = local[1] - surf->plane->normal[1] * dist;
179                         impact[2] = local[2] - surf->plane->normal[2] * dist;
180                 }
181
182                 impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
183                 impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
184
185                 td = bound(0, impacts, smax * 16) - impacts;
186                 td1 = bound(0, impactt, tmax * 16) - impactt;
187                 td = td * td + td1 * td1 + dist2;
188                 if (td > maxdist)
189                         continue;
190
191                 // reduce calculations
192                 for (s = 0, td1 = impacts; s < smax; s++, td1 -= 16.0f)
193                         sdtable[s] = td1 * td1 + dist2;
194
195                 maxdist3 = maxdist - dist2;
196
197                 // convert to 8.8 blocklights format
198                 red = r_dlight[lnum].light[0];
199                 green = r_dlight[lnum].light[1];
200                 blue = r_dlight[lnum].light[2];
201                 subtract = r_dlight[lnum].subtract * 32768.0f;
202                 bl = floatblocklights;
203
204                 td1 = impactt;
205                 for (t = 0;t < tmax;t++, td1 -= 16.0f)
206                 {
207                         td = td1 * td1;
208                         // make sure some part of it is visible on this line
209                         if (td < maxdist3)
210                         {
211                                 maxdist2 = maxdist - td;
212                                 for (s = 0;s < smax;s++)
213                                 {
214                                         if (sdtable[s] < maxdist2)
215                                         {
216                                                 k = (32768.0f / (sdtable[s] + td)) - subtract;
217                                                 bl[0] += red   * k;
218                                                 bl[1] += green * k;
219                                                 bl[2] += blue  * k;
220                                                 lit = true;
221                                         }
222                                         bl += 3;
223                                 }
224                         }
225                         else // skip line
226                                 bl += smax3;
227                 }
228         }
229         return lit;
230 }
231
232 /*
233 ===============
234 R_BuildLightMap
235
236 Combine and scale multiple lightmaps into the 8.8 format in blocklights
237 ===============
238 */
239 static void R_BuildLightMap (msurface_t *surf, int dlightchanged)
240 {
241         if (!r_floatbuildlightmap.integer)
242         {
243                 int smax, tmax, i, j, size, size3, shift, maps, stride, l;
244                 unsigned int *bl, scale;
245                 qbyte *lightmap, *out, *stain;
246
247                 // update cached lighting info
248                 surf->cached_dlight = 0;
249                 surf->cached_lightscalebit = lightscalebit;
250                 surf->cached_ambient = r_ambient.value;
251                 surf->cached_light[0] = d_lightstylevalue[surf->styles[0]];
252                 surf->cached_light[1] = d_lightstylevalue[surf->styles[1]];
253                 surf->cached_light[2] = d_lightstylevalue[surf->styles[2]];
254                 surf->cached_light[3] = d_lightstylevalue[surf->styles[3]];
255
256                 smax = (surf->extents[0]>>4)+1;
257                 tmax = (surf->extents[1]>>4)+1;
258                 size = smax*tmax;
259                 size3 = size*3;
260                 lightmap = surf->samples;
261
262         // set to full bright if no light data
263                 bl = intblocklights;
264                 if ((currentrenderentity->effects & EF_FULLBRIGHT) || !currentrenderentity->model->lightdata)
265                 {
266                         for (i = 0;i < size3;i++)
267                                 bl[i] = 255*256;
268                 }
269                 else
270                 {
271         // clear to no light
272                         j = r_ambient.value * 512.0f; // would be 128.0f logically, but using 512.0f to match winquake style
273                         if (j)
274                         {
275                                 for (i = 0;i < size3;i++)
276                                         *bl++ = j;
277                         }
278                         else
279                                 memset(bl, 0, size*3*sizeof(unsigned int));
280
281                         if (surf->dlightframe == r_framecount && r_dlightmap.integer)
282                         {
283                                 surf->cached_dlight = R_IntAddDynamicLights(surf);
284                                 if (surf->cached_dlight)
285                                         c_light_polys++;
286                                 else if (dlightchanged)
287                                         return; // don't upload if only updating dlights and none mattered
288                         }
289
290         // add all the lightmaps
291                         if (lightmap)
292                         {
293                                 bl = intblocklights;
294                                 for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++, lightmap += size3)
295                                         for (scale = d_lightstylevalue[surf->styles[maps]], i = 0;i < size3;i++)
296                                                 bl[i] += lightmap[i] * scale;
297                         }
298                 }
299
300                 stain = surf->stainsamples;
301                 bl = intblocklights;
302                 out = templight;
303                 // deal with lightmap brightness scale
304                 shift = 7 + lightscalebit + 8;
305                 if (currentrenderentity->model->lightmaprgba)
306                 {
307                         stride = (surf->lightmaptexturestride - smax) * 4;
308                         for (i = 0;i < tmax;i++, out += stride)
309                         {
310                                 for (j = 0;j < smax;j++)
311                                 {
312                                         l = (*bl++ * *stain++) >> shift;*out++ = min(l, 255);
313                                         l = (*bl++ * *stain++) >> shift;*out++ = min(l, 255);
314                                         l = (*bl++ * *stain++) >> shift;*out++ = min(l, 255);
315                                         *out++ = 255;
316                                 }
317                         }
318                 }
319                 else
320                 {
321                         stride = (surf->lightmaptexturestride - smax) * 3;
322                         for (i = 0;i < tmax;i++, out += stride)
323                         {
324                                 for (j = 0;j < smax;j++)
325                                 {
326                                         l = (*bl++ * *stain++) >> shift;*out++ = min(l, 255);
327                                         l = (*bl++ * *stain++) >> shift;*out++ = min(l, 255);
328                                         l = (*bl++ * *stain++) >> shift;*out++ = min(l, 255);
329                                 }
330                         }
331                 }
332
333                 R_UpdateTexture(surf->lightmaptexture, templight);
334         }
335         else
336         {
337                 int smax, tmax, i, j, size, size3, maps, stride, l;
338                 float *bl, scale;
339                 qbyte *lightmap, *out, *stain;
340
341                 // update cached lighting info
342                 surf->cached_dlight = 0;
343                 surf->cached_lightscalebit = lightscalebit;
344                 surf->cached_ambient = r_ambient.value;
345                 surf->cached_light[0] = d_lightstylevalue[surf->styles[0]];
346                 surf->cached_light[1] = d_lightstylevalue[surf->styles[1]];
347                 surf->cached_light[2] = d_lightstylevalue[surf->styles[2]];
348                 surf->cached_light[3] = d_lightstylevalue[surf->styles[3]];
349
350                 smax = (surf->extents[0]>>4)+1;
351                 tmax = (surf->extents[1]>>4)+1;
352                 size = smax*tmax;
353                 size3 = size*3;
354                 lightmap = surf->samples;
355
356         // set to full bright if no light data
357                 bl = floatblocklights;
358                 if ((currentrenderentity->effects & EF_FULLBRIGHT) || !currentrenderentity->model->lightdata)
359                         j = 255*256;
360                 else
361                         j = r_ambient.value * 512.0f; // would be 128.0f logically, but using 512.0f to match winquake style
362
363                 // clear to no light
364                 if (j)
365                 {
366                         for (i = 0;i < size3;i++)
367                                 *bl++ = j;
368                 }
369                 else
370                         memset(bl, 0, size*3*sizeof(float));
371
372                 if (surf->dlightframe == r_framecount && r_dlightmap.integer)
373                 {
374                         surf->cached_dlight = R_FloatAddDynamicLights(surf);
375                         if (surf->cached_dlight)
376                                 c_light_polys++;
377                         else if (dlightchanged)
378                                 return; // don't upload if only updating dlights and none mattered
379                 }
380
381                 // add all the lightmaps
382                 if (lightmap)
383                 {
384                         bl = floatblocklights;
385                         for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++, lightmap += size3)
386                                 for (scale = d_lightstylevalue[surf->styles[maps]], i = 0;i < size3;i++)
387                                         bl[i] += lightmap[i] * scale;
388                 }
389
390                 stain = surf->stainsamples;
391                 bl = floatblocklights;
392                 out = templight;
393                 // deal with lightmap brightness scale
394                 scale = 1.0f / (1 << (7 + lightscalebit + 8));
395                 if (currentrenderentity->model->lightmaprgba)
396                 {
397                         stride = (surf->lightmaptexturestride - smax) * 4;
398                         for (i = 0;i < tmax;i++, out += stride)
399                         {
400                                 for (j = 0;j < smax;j++)
401                                 {
402                                         l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
403                                         l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
404                                         l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
405                                         *out++ = 255;
406                                 }
407                         }
408                 }
409                 else
410                 {
411                         stride = (surf->lightmaptexturestride - smax) * 3;
412                         for (i = 0;i < tmax;i++, out += stride)
413                         {
414                                 for (j = 0;j < smax;j++)
415                                 {
416                                         l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
417                                         l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
418                                         l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
419                                 }
420                         }
421                 }
422
423                 R_UpdateTexture(surf->lightmaptexture, templight);
424         }
425 }
426
427 void R_StainNode (mnode_t *node, model_t *model, vec3_t origin, float radius, int icolor[8])
428 {
429         float ndist;
430         msurface_t *surf, *endsurf;
431         int sdtable[256], td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, smax3, dist2, impacts, impactt, subtract, a, stained, cr, cg, cb, ca, ratio;
432         qbyte *bl;
433         vec3_t impact;
434         // LordHavoc: use 64bit integer...  shame it's not very standardized...
435 #if _MSC_VER || __BORLANDC__
436         __int64     k;
437 #else
438         long long   k;
439 #endif
440
441
442         // for comparisons to minimum acceptable light
443         // compensate for 4096 offset
444         maxdist = radius * radius + 4096;
445
446         // clamp radius to avoid exceeding 32768 entry division table
447         if (maxdist > 4194304)
448                 maxdist = 4194304;
449
450         subtract = (int) ((1.0f / maxdist) * 4194304.0f);
451
452 loc0:
453         if (node->contents < 0)
454                 return;
455         ndist = PlaneDiff(origin, node->plane);
456         if (ndist > radius)
457         {
458                 node = node->children[0];
459                 goto loc0;
460         }
461         if (ndist < -radius)
462         {
463                 node = node->children[1];
464                 goto loc0;
465         }
466
467         dist2 = ndist * ndist;
468         dist2 += 4096.0f;
469         if (dist2 < maxdist)
470         {
471                 maxdist3 = maxdist - dist2;
472
473                 if (node->plane->type < 3)
474                 {
475                         VectorCopy(origin, impact);
476                         impact[node->plane->type] -= ndist;
477                 }
478                 else
479                 {
480                         impact[0] = origin[0] - node->plane->normal[0] * ndist;
481                         impact[1] = origin[1] - node->plane->normal[1] * ndist;
482                         impact[2] = origin[2] - node->plane->normal[2] * ndist;
483                 }
484
485                 for (surf = model->surfaces + node->firstsurface, endsurf = surf + node->numsurfaces;surf < endsurf;surf++)
486                 {
487                         if (surf->stainsamples)
488                         {
489                                 smax = (surf->extents[0] >> 4) + 1;
490                                 tmax = (surf->extents[1] >> 4) + 1;
491
492                                 impacts = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
493                                 impactt = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
494
495                                 s = bound(0, impacts, smax * 16) - impacts;
496                                 t = bound(0, impactt, tmax * 16) - impactt;
497                                 i = s * s + t * t + dist2;
498                                 if (i > maxdist)
499                                         continue;
500
501                                 // reduce calculations
502                                 for (s = 0, i = impacts; s < smax; s++, i -= 16)
503                                         sdtable[s] = i * i + dist2;
504
505                                 // convert to 8.8 blocklights format
506                                 bl = surf->stainsamples;
507                                 smax3 = smax * 3;
508                                 stained = false;
509
510                                 i = impactt;
511                                 for (t = 0;t < tmax;t++, i -= 16)
512                                 {
513                                         td = i * i;
514                                         // make sure some part of it is visible on this line
515                                         if (td < maxdist3)
516                                         {
517                                                 maxdist2 = maxdist - td;
518                                                 for (s = 0;s < smax;s++)
519                                                 {
520                                                         if (sdtable[s] < maxdist2)
521                                                         {
522                                                                 k = dlightdivtable[(sdtable[s] + td) >> 7] - subtract;
523                                                                 if (k > 0)
524                                                                 {
525                                                                         ratio = rand() & 255;
526                                                                         ca = (((icolor[7] - icolor[3]) * ratio) >> 8) + icolor[3];
527                                                                         a = (ca * k) >> 8;
528                                                                         if (a > 0)
529                                                                         {
530                                                                                 a = bound(0, a, 256);
531                                                                                 cr = (((icolor[4] - icolor[0]) * ratio) >> 8) + icolor[0];
532                                                                                 cg = (((icolor[5] - icolor[1]) * ratio) >> 8) + icolor[1];
533                                                                                 cb = (((icolor[6] - icolor[2]) * ratio) >> 8) + icolor[2];
534                                                                                 bl[0] = (qbyte) ((((cr - (int) bl[0]) * a) >> 8) + (int) bl[0]);
535                                                                                 bl[1] = (qbyte) ((((cg - (int) bl[1]) * a) >> 8) + (int) bl[1]);
536                                                                                 bl[2] = (qbyte) ((((cb - (int) bl[2]) * a) >> 8) + (int) bl[2]);
537                                                                                 stained = true;
538                                                                         }
539                                                                 }
540                                                         }
541                                                         bl += 3;
542                                                 }
543                                         }
544                                         else // skip line
545                                                 bl += smax3;
546                                 }
547                                 // force lightmap upload
548                                 if (stained)
549                                         surf->cached_dlight = true;
550                         }
551                 }
552         }
553
554         if (node->children[0]->contents >= 0)
555         {
556                 if (node->children[1]->contents >= 0)
557                 {
558                         R_StainNode(node->children[0], model, origin, radius, icolor);
559                         node = node->children[1];
560                         goto loc0;
561                 }
562                 else
563                 {
564                         node = node->children[0];
565                         goto loc0;
566                 }
567         }
568         else if (node->children[1]->contents >= 0)
569         {
570                 node = node->children[1];
571                 goto loc0;
572         }
573 }
574
575 void R_Stain (vec3_t origin, float radius, int cr1, int cg1, int cb1, int ca1, int cr2, int cg2, int cb2, int ca2)
576 {
577         int n, icolor[8];
578         entity_render_t *ent;
579         model_t *model;
580         vec3_t org;
581         icolor[0] = cr1;
582         icolor[1] = cg1;
583         icolor[2] = cb1;
584         icolor[3] = ca1;
585         icolor[4] = cr2;
586         icolor[5] = cg2;
587         icolor[6] = cb2;
588         icolor[7] = ca2;
589
590         model = cl.worldmodel;
591         softwaretransformidentity();
592         R_StainNode(model->nodes + model->hulls[0].firstclipnode, model, origin, radius, icolor);
593
594         // look for embedded bmodels
595         for (n = 0;n < cl_num_brushmodel_entities;n++)
596         {
597                 ent = cl_brushmodel_entities[n];
598                 model = ent->model;
599                 if (model && model->name[0] == '*')
600                 {
601                         Mod_CheckLoaded(model);
602                         if (model->type == mod_brush)
603                         {
604                                 softwaretransformforentity(ent);
605                                 softwareuntransform(origin, org);
606                                 R_StainNode(model->nodes + model->hulls[0].firstclipnode, model, org, radius, icolor);
607                         }
608                 }
609         }
610 }
611
612
613 /*
614 =============================================================
615
616         BRUSH MODELS
617
618 =============================================================
619 */
620
621
622 static float turbsin[256] =
623 {
624         #include "gl_warp_sin.h"
625 };
626 #define TURBSCALE (256.0 / (2 * M_PI))
627
628 // only need to hold as many verts as the mesh splitter will allow in model_brush.c
629 #define MAX_SURFVERTS 3072
630 typedef struct
631 {
632         float v[4];
633         float st[2];
634         float uv[2];
635         float c[4];
636 }
637 surfvert_t;
638 static surfvert_t svert[MAX_SURFVERTS]; // used by the following functions
639
640 static void RSurfShader_Sky(msurface_t *firstsurf)
641 {
642         msurface_t *surf;
643         int i;
644         float number, length, dir[3], speedscale;
645         surfvertex_t *v;
646         surfvert_t *sv;
647         surfmesh_t *mesh;
648         rmeshinfo_t m;
649
650         // LordHavoc: HalfLife maps have freaky skypolys...
651         if (currentrenderentity->model->ishlbsp)
652                 return;
653
654         if (skyrendermasked)
655         {
656                 if (skyrendernow)
657                 {
658                         skyrendernow = false;
659                         R_Sky();
660                 }
661                 for (surf = firstsurf;surf;surf = surf->chain)
662                 {
663                         // draw depth-only polys
664                         memset(&m, 0, sizeof(m));
665                         m.transparent = false;
666                         m.blendfunc1 = GL_ZERO;
667                         m.blendfunc2 = GL_ONE;
668                         m.depthwrite = true;
669                         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
670                         {
671                                 m.numtriangles = mesh->numtriangles;
672                                 m.numverts = mesh->numverts;
673                                 m.index = mesh->index;
674                                 if (softwaretransform_complexity)
675                                 {
676                                         m.vertex = &svert[0].v[0];
677                                         m.vertexstep = sizeof(surfvert_t);
678                                         for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
679                                                 softwaretransform(v->v, sv->v);
680                                 }
681                                 else
682                                 {
683                                         m.vertex = &mesh->vertex[0].v[0];
684                                         m.vertexstep = sizeof(surfvertex_t);
685                                 }
686                                 R_Mesh_Draw(&m);
687                         }
688                 }
689         }
690         else if (skyrenderglquake)
691         {
692                 for (surf = firstsurf;surf;surf = surf->chain)
693                 {
694                         memset(&m, 0, sizeof(m));
695                         m.transparent = false;
696                         m.blendfunc1 = GL_ONE;
697                         m.blendfunc2 = GL_ZERO;
698                         m.vertex = &svert[0].v[0];
699                         m.vertexstep = sizeof(surfvert_t);
700                         m.cr = 1;
701                         m.cg = 1;
702                         m.cb = 1;
703                         m.ca = 1;
704                         m.tex[0] = R_GetTexture(solidskytexture);
705                         m.texcoords[0] = &svert[0].st[0];
706                         m.texcoordstep[0] = sizeof(surfvert_t);
707                         speedscale = cl.time * (8.0/128.0);
708                         speedscale -= (int)speedscale;
709                         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
710                         {
711                                 m.numtriangles = mesh->numtriangles;
712                                 m.numverts = mesh->numverts;
713                                 m.index = mesh->index;
714                                 for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
715                                 {
716                                         softwaretransform(v->v, sv->v);
717                                         VectorSubtract (sv->v, r_origin, dir);
718                                         // flatten the sphere
719                                         dir[2] *= 3;
720
721                                         number = DotProduct(dir, dir);
722                                         #if SLOWMATH
723                                         length = 3.0f / sqrt(number);
724                                         #else
725                                         *((int *)&length) = 0x5f3759df - ((* (int *) &number) >> 1);
726                                         length = 3.0f * (length * (1.5f - (number * 0.5f * length * length)));
727                                         #endif
728
729                                         sv->st[0] = speedscale + dir[0] * length;
730                                         sv->st[1] = speedscale + dir[1] * length;
731                                 }
732                                 R_Mesh_Draw(&m);
733                         }
734                 }
735         }
736         else
737         {
738                 for (surf = firstsurf;surf;surf = surf->chain)
739                 {
740                         // flat color
741                         memset(&m, 0, sizeof(m));
742                         m.transparent = false;
743                         m.blendfunc1 = GL_ONE;
744                         m.blendfunc2 = GL_ZERO;
745                         m.cr = fogcolor[0];
746                         m.cg = fogcolor[1];
747                         m.cb = fogcolor[2];
748                         m.ca = 1;
749                         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
750                         {
751                                 m.numtriangles = mesh->numtriangles;
752                                 m.numverts = mesh->numverts;
753                                 m.index = mesh->index;
754                                 if (softwaretransform_complexity)
755                                 {
756                                         m.vertex = &svert[0].v[0];
757                                         m.vertexstep = sizeof(surfvert_t);
758                                         for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
759                                                 softwaretransform(v->v, sv->v);
760                                 }
761                                 else
762                                 {
763                                         m.vertex = &mesh->vertex[0].v[0];
764                                         m.vertexstep = sizeof(surfvertex_t);
765                                 }
766                                 R_Mesh_Draw(&m);
767                         }
768                 }
769         }
770         if (skyrenderglquake)
771         {
772                 for (surf = firstsurf;surf;surf = surf->chain)
773                 {
774                         memset(&m, 0, sizeof(m));
775                         m.transparent = false;
776                         m.blendfunc1 = GL_SRC_ALPHA;
777                         m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
778                         m.vertex = &svert[0].v[0];
779                         m.vertexstep = sizeof(surfvert_t);
780                         m.cr = 1;
781                         m.cg = 1;
782                         m.cb = 1;
783                         m.ca = 1;
784                         m.tex[0] = R_GetTexture(alphaskytexture);
785                         m.texcoords[0] = &svert[0].st[0];
786                         m.texcoordstep[0] = sizeof(surfvert_t);
787                         speedscale = cl.time * (16.0/128.0);
788                         speedscale -= (int)speedscale;
789                         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
790                         {
791                                 m.numtriangles = mesh->numtriangles;
792                                 m.numverts = mesh->numverts;
793                                 m.index = mesh->index;
794                                 for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
795                                 {
796                                         softwaretransform(v->v, sv->v);
797                                         VectorSubtract (sv->v, r_origin, dir);
798                                         // flatten the sphere
799                                         dir[2] *= 3;
800
801                                         number = DotProduct(dir, dir);
802                                         #if SLOWMATH
803                                         length = 3.0f / sqrt(number);
804                                         #else
805                                         *((int *)&length) = 0x5f3759df - ((* (int *) &number) >> 1);
806                                         length = 3.0f * (length * (1.5f - (number * 0.5f * length * length)));
807                                         #endif
808
809                                         sv->st[0] = speedscale + dir[0] * length;
810                                         sv->st[1] = speedscale + dir[1] * length;
811                                 }
812                                 R_Mesh_Draw(&m);
813                         }
814                 }
815         }
816 }
817
818 static int RSurf_Light(int *dlightbits, int numverts)
819 {
820         float f;
821         int i, l, lit = false;
822         rdlight_t *rd;
823         vec3_t lightorigin;
824         surfvert_t *sv;
825         for (l = 0;l < r_numdlights;l++)
826         {
827                 if (dlightbits[l >> 5] & (1 << (l & 31)))
828                 {
829                         rd = &r_dlight[l];
830                         // FIXME: support softwareuntransform here and make bmodels use hardware transform?
831                         VectorCopy(rd->origin, lightorigin);
832                         for (i = 0, sv = svert;i < numverts;i++, sv++)
833                         {
834                                 f = VectorDistance2(sv->v, lightorigin);
835                                 if (f < rd->cullradius2)
836                                 {
837                                         f = (1.0f / f) - rd->subtract;
838                                         sv->c[0] += rd->light[0] * f;
839                                         sv->c[1] += rd->light[1] * f;
840                                         sv->c[2] += rd->light[2] * f;
841                                         lit = true;
842                                 }
843                         }
844                 }
845         }
846         return lit;
847 }
848
849 #if USEMESHBUFFER
850 static int RSurf_LightSeparate(int *dlightbits, int numverts, float *vert, float *color)
851 {
852         float f, *v, *c;
853         int i, l, lit = false;
854         rdlight_t *rd;
855         vec3_t lightorigin;
856         for (l = 0;l < r_numdlights;l++)
857         {
858                 if (dlightbits[l >> 5] & (1 << (l & 31)))
859                 {
860                         rd = &r_dlight[l];
861                         // FIXME: support softwareuntransform here and make bmodels use hardware transform?
862                         VectorCopy(rd->origin, lightorigin);
863                         for (i = 0, v = vert, c = color;i < numverts;i++, v += 4, c += 4)
864                         {
865                                 f = VectorDistance2(v, lightorigin) + LIGHTOFFSET;
866                                 if (f < rd->cullradius2)
867                                 {
868                                         f = (1.0f / f) - rd->subtract;
869                                         VectorMA(c, f, rd->light, c);
870                                         lit = true;
871                                 }
872                         }
873                 }
874         }
875         return lit;
876 }
877
878 // note: this untransforms lights to do the checking,
879 // and takes surf->mesh->vertex data
880 static int RSurf_LightCheck(int *dlightbits, surfmesh_t *mesh)
881 {
882         int i, l;
883         rdlight_t *rd;
884         vec3_t lightorigin;
885         surfvertex_t *sv;
886         for (l = 0;l < r_numdlights;l++)
887         {
888                 if (dlightbits[l >> 5] & (1 << (l & 31)))
889                 {
890                         rd = &r_dlight[l];
891                         softwareuntransform(rd->origin, lightorigin);
892                         for (i = 0, sv = mesh->vertex;i < mesh->numverts;i++, sv++)
893                                 if (VectorDistance2(sv->v, lightorigin) < rd->cullradius2)
894                                         return true;
895                 }
896         }
897         return false;
898 }
899 #endif
900
901 static void RSurfShader_Water_Pass_Base(msurface_t *surf)
902 {
903 #if 0
904         int i, size3;
905         surfvertex_t *v;
906         float *outv, *outc, *outst, *outuv, cl, ca, diff[3];
907         float base[3], scale, f;
908         qbyte *lm;
909         surfmesh_t *mesh;
910         rmeshbufferinfo_t m;
911         memset(&m, 0, sizeof(m));
912         if (currentrenderentity->effects & EF_ADDITIVE)
913         {
914                 m.transparent = true;
915                 m.blendfunc1 = GL_SRC_ALPHA;
916                 m.blendfunc2 = GL_ONE;
917         }
918         else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
919         {
920                 m.transparent = true;
921                 m.blendfunc1 = GL_SRC_ALPHA;
922                 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
923         }
924         else
925         {
926                 m.transparent = false;
927                 m.blendfunc1 = GL_ONE;
928                 m.blendfunc2 = GL_ZERO;
929         }
930         m.depthwrite = false;
931         m.depthdisable = false;
932         m.tex[0] = R_GetTexture(surf->currenttexture->texture);
933
934         size3 = ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3;
935
936         base[0] = base[1] = base[2] = currentrenderentity->effects & EF_FULLBRIGHT ? 2.0f : r_ambient.value * (1.0f / 64.0f) + surf->flags & SURF_LIGHTMAP ? 0 : ;
937
938         ca = currentrenderentity->alpha;
939         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
940         {
941                 m.numtriangles = mesh->numtriangles;
942                 m.numverts = mesh->numverts;
943
944                 if (R_Mesh_Draw_GetBuffer(&m))
945                 {
946                         cl = m.colorscale;
947                         memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
948
949                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2)
950                         {
951                                 softwaretransform(v->v, outv);
952                                 outv[3] = 1;
953                                 VectorCopy(base, outc);
954                                 outc[3] = ca;
955                                 outst[0] = v->st[0];
956                                 outst[1] = v->st[1];
957                         }
958
959                         if (surf->dlightframe == r_framecount)
960                                 RSurf_LightSeparate(surf->dlightbits, m.numverts, m.vertex, m.color);
961
962                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color;i < m.numverts;i++, v++, outv += 4, outc += 4)
963                         {
964                                 if (surf->flags & SURF_LIGHTMAP)
965                                 if (surf->styles[0] != 255)
966                                 {
967                                         lm = surf->samples + v->lightmapoffset;
968                                         scale = d_lightstylevalue[surf->styles[0]] * (1.0f / 32768.0f);
969                                         VectorMA(outc, scale, lm, outc);
970                                         if (surf->styles[1] != 255)
971                                         {
972                                                 lm += size3;
973                                                 scale = d_lightstylevalue[surf->styles[1]] * (1.0f / 32768.0f);
974                                                 VectorMA(outc, scale, lm, outc);
975                                                 if (surf->styles[2] != 255)
976                                                 {
977                                                         lm += size3;
978                                                         scale = d_lightstylevalue[surf->styles[2]] * (1.0f / 32768.0f);
979                                                         VectorMA(outc, scale, lm, outc);
980                                                         if (surf->styles[3] != 255)
981                                                         {
982                                                                 lm += size3;
983                                                                 scale = d_lightstylevalue[surf->styles[3]] * (1.0f / 32768.0f);
984                                                                 VectorMA(outc, scale, lm, outc);
985                                                         }
986                                                 }
987                                         }
988                                 }
989                                 if (fogenabled)
990                                 {
991                                         VectorSubtract(outv, r_origin, diff);
992                                         f = cl * (1 - exp(fogdensity/DotProduct(diff, diff)));
993                                         VectorScale(outc, f, outc);
994                                 }
995                                 else
996                                         VectorScale(outc, cl, outc);
997                         }
998                 }
999         }
1000         int i;
1001         surfvertex_t *v;
1002         float *outv, *outc, *outst, *outuv, cl, ca, diff[3];
1003         surfmesh_t *mesh;
1004         rmeshbufferinfo_t m;
1005         memset(&m, 0, sizeof(m));
1006         if (currentrenderentity->effects & EF_ADDITIVE)
1007         {
1008                 m.transparent = true;
1009                 m.blendfunc1 = GL_SRC_ALPHA;
1010                 m.blendfunc2 = GL_ONE;
1011         }
1012         else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
1013         {
1014                 m.transparent = true;
1015                 m.blendfunc1 = GL_SRC_ALPHA;
1016                 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1017         }
1018         else
1019         {
1020                 m.transparent = false;
1021                 m.blendfunc1 = GL_ONE;
1022                 m.blendfunc2 = GL_ZERO;
1023         }
1024         m.depthwrite = false;
1025         m.depthdisable = false;
1026         m.tex[0] = R_GetTexture(surf->currenttexture->texture);
1027         m.tex[1] = R_GetTexture(surf->lightmaptexture);
1028         ca = currentrenderentity->alpha;
1029         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1030         {
1031                 m.numtriangles = mesh->numtriangles;
1032                 m.numverts = mesh->numverts;
1033
1034                 if (R_Mesh_Draw_GetBuffer(&m))
1035                 {
1036                         cl = (float) (1 << lightscalebit) * m.colorscale;
1037                         memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1038                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2)
1039                         {
1040                                 softwaretransform(v->v, outv);
1041                                 if (r_waterripple.value)
1042                                         outv[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];
1043                                 outv[3] = 1;
1044                                 if (fogenabled)
1045                                 {
1046                                         VectorSubtract(outv, r_origin, diff);
1047                                         outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff)));
1048                                 }
1049                                 else
1050                                         outc[0] = outc[1] = outc[2] = cl;
1051                                 outc[3] = ca;
1052                                 outst[0] = v->st[0];
1053                                 outst[1] = v->st[1];
1054                                 outuv[0] = v->uv[0];
1055                                 outuv[1] = v->uv[1];
1056                         }
1057                 }
1058         }
1059 #else
1060         int i;
1061         float diff[3], alpha, ifog;
1062         surfvertex_t *v;
1063         surfvert_t *sv;
1064         surfmesh_t *mesh;
1065         rmeshinfo_t m;
1066         alpha = currentrenderentity->alpha * (surf->flags & SURF_DRAWNOALPHA ? 1 : r_wateralpha.value);
1067
1068         memset(&m, 0, sizeof(m));
1069         if (alpha != 1 || surf->currenttexture->fogtexture != NULL)
1070         {
1071                 m.transparent = true;
1072                 m.blendfunc1 = GL_SRC_ALPHA;
1073                 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1074         }
1075         else
1076         {
1077                 m.transparent = false;
1078                 m.blendfunc1 = GL_ONE;
1079                 m.blendfunc2 = GL_ZERO;
1080         }
1081         m.vertex = &svert[0].v[0];
1082         m.vertexstep = sizeof(surfvert_t);
1083         m.color = &svert[0].c[0];
1084         m.colorstep = sizeof(surfvert_t);
1085         m.tex[0] = R_GetTexture(surf->currenttexture->texture);
1086         m.texcoords[0] = &svert[0].st[0];
1087         m.texcoordstep[0] = sizeof(surfvert_t);
1088         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1089         {
1090                 m.numtriangles = mesh->numtriangles;
1091                 m.numverts = mesh->numverts;
1092                 m.index = mesh->index;
1093                 for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
1094                 {
1095                         softwaretransform(v->v, sv->v);
1096                         if (r_waterripple.value)
1097                                 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];
1098                         if (surf->flags & SURF_DRAWFULLBRIGHT)
1099                         {
1100                                 sv->c[0] = 1;
1101                                 sv->c[1] = 1;
1102                                 sv->c[2] = 1;
1103                                 sv->c[3] = alpha;
1104                         }
1105                         else
1106                         {
1107                                 sv->c[0] = 0.5f;
1108                                 sv->c[1] = 0.5f;
1109                                 sv->c[2] = 0.5f;
1110                                 sv->c[3] = alpha;
1111                         }
1112                         sv->st[0] = (v->st[0] + turbsin[(int)((v->st[1]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f);
1113                         sv->st[1] = (v->st[1] + turbsin[(int)((v->st[0]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f);
1114                 }
1115                 if (surf->dlightframe == r_framecount && !(surf->flags & SURF_DRAWFULLBRIGHT))
1116                         RSurf_Light(surf->dlightbits, m.numverts);
1117                 if (fogenabled && (surf->flags & SURF_DRAWNOALPHA))
1118                 {
1119                         for (i = 0, sv = svert;i < m.numverts;i++, sv++)
1120                         {
1121                                 VectorSubtract(sv->v, r_origin, diff);
1122                                 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
1123                                 sv->c[0] *= ifog;
1124                                 sv->c[1] *= ifog;
1125                                 sv->c[2] *= ifog;
1126                         }
1127                 }
1128                 R_Mesh_Draw(&m);
1129         }
1130 #endif
1131 }
1132
1133 static void RSurfShader_Water_Pass_Fog(msurface_t *surf)
1134 {
1135 #if 0
1136 #else
1137         int i;
1138         float alpha;
1139         surfvertex_t *v;
1140         surfvert_t *sv;
1141         surfmesh_t *mesh;
1142         rmeshinfo_t m;
1143         vec3_t diff;
1144         alpha = currentrenderentity->alpha * (surf->flags & SURF_DRAWNOALPHA ? 1 : r_wateralpha.value);
1145
1146         memset(&m, 0, sizeof(m));
1147         m.transparent = alpha != 1 || surf->currenttexture->fogtexture != NULL;
1148         m.blendfunc1 = GL_SRC_ALPHA;
1149         m.blendfunc2 = GL_ONE;
1150         m.vertex = &svert[0].v[0];
1151         m.vertexstep = sizeof(surfvert_t);
1152         m.color = &svert[0].c[0];
1153         m.colorstep = sizeof(surfvert_t);
1154         m.tex[0] = R_GetTexture(surf->currenttexture->fogtexture);
1155         m.texcoords[0] = &svert[0].st[0];
1156         m.texcoordstep[0] = sizeof(surfvert_t);
1157
1158         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1159         {
1160                 m.numtriangles = mesh->numtriangles;
1161                 m.numverts = mesh->numverts;
1162                 m.index = mesh->index;
1163                 for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
1164                 {
1165                         softwaretransform(v->v, sv->v);
1166                         if (r_waterripple.value)
1167                                 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];
1168                         if (m.tex[0])
1169                         {
1170                                 sv->st[0] = (v->st[0] + turbsin[(int)((v->st[1]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f);
1171                                 sv->st[1] = (v->st[1] + turbsin[(int)((v->st[0]*0.125f+cl.time) * TURBSCALE) & 255]) * (1.0f / 64.0f);
1172                         }
1173                         VectorSubtract(sv->v, r_origin, diff);
1174                         sv->c[0] = fogcolor[0];
1175                         sv->c[1] = fogcolor[1];
1176                         sv->c[2] = fogcolor[2];
1177                         sv->c[3] = alpha * exp(fogdensity/DotProduct(diff, diff));
1178                 }
1179                 R_Mesh_Draw(&m);
1180         }
1181 #endif
1182 }
1183
1184 static void RSurfShader_Water(msurface_t *firstsurf)
1185 {
1186         msurface_t *surf;
1187         for (surf = firstsurf;surf;surf = surf->chain)
1188                 RSurfShader_Water_Pass_Base(surf);
1189         if (fogenabled)
1190                 for (surf = firstsurf;surf;surf = surf->chain)
1191                         RSurfShader_Water_Pass_Fog(surf);
1192 }
1193
1194 static void RSurfShader_Wall_Pass_BaseMTex(msurface_t *surf)
1195 {
1196 #if USEMESHBUFFER
1197         int i;
1198         surfvertex_t *v;
1199         float *outv, *outc, *outst, *outuv, cl, ca, diff[3];
1200         surfmesh_t *mesh;
1201         rmeshbufferinfo_t m;
1202         memset(&m, 0, sizeof(m));
1203         if (currentrenderentity->effects & EF_ADDITIVE)
1204         {
1205                 m.transparent = true;
1206                 m.blendfunc1 = GL_SRC_ALPHA;
1207                 m.blendfunc2 = GL_ONE;
1208         }
1209         else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
1210         {
1211                 m.transparent = true;
1212                 m.blendfunc1 = GL_SRC_ALPHA;
1213                 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1214         }
1215         else
1216         {
1217                 m.transparent = false;
1218                 m.blendfunc1 = GL_ONE;
1219                 m.blendfunc2 = GL_ZERO;
1220         }
1221         m.depthwrite = false;
1222         m.depthdisable = false;
1223         m.tex[0] = R_GetTexture(surf->currenttexture->texture);
1224         m.tex[1] = R_GetTexture(surf->lightmaptexture);
1225         ca = currentrenderentity->alpha;
1226         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1227         {
1228                 m.numtriangles = mesh->numtriangles;
1229                 m.numverts = mesh->numverts;
1230
1231                 if (R_Mesh_Draw_GetBuffer(&m))
1232                 {
1233                         cl = (float) (1 << lightscalebit) * m.colorscale;
1234                         memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1235                         if (fogenabled)
1236                         {
1237                                 if (softwaretransform_complexity)
1238                                 {
1239                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2)
1240                                         {
1241                                                 softwaretransform(v->v, outv);
1242                                                 outv[3] = 1;
1243                                                 VectorSubtract(outv, r_origin, diff);
1244                                                 outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff)));
1245                                                 outc[3] = ca;
1246                                                 outst[0] = v->st[0];
1247                                                 outst[1] = v->st[1];
1248                                                 outuv[0] = v->uv[0];
1249                                                 outuv[1] = v->uv[1];
1250                                         }
1251                                 }
1252                                 else
1253                                 {
1254                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2)
1255                                         {
1256                                                 VectorCopy(v->v, outv);
1257                                                 outv[3] = 1;
1258                                                 VectorSubtract(outv, r_origin, diff);
1259                                                 outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff)));
1260                                                 outc[3] = ca;
1261                                                 outst[0] = v->st[0];
1262                                                 outst[1] = v->st[1];
1263                                                 outuv[0] = v->uv[0];
1264                                                 outuv[1] = v->uv[1];
1265                                         }
1266                                 }
1267                         }
1268                         else
1269                         {
1270                                 if (softwaretransform_complexity)
1271                                 {
1272                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2)
1273                                         {
1274                                                 softwaretransform(v->v, outv);
1275                                                 outv[3] = 1;
1276                                                 outc[0] = outc[1] = outc[2] = cl;
1277                                                 outc[3] = ca;
1278                                                 outst[0] = v->st[0];
1279                                                 outst[1] = v->st[1];
1280                                                 outuv[0] = v->uv[0];
1281                                                 outuv[1] = v->uv[1];
1282                                         }
1283                                 }
1284                                 else
1285                                 {
1286                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2)
1287                                         {
1288                                                 VectorCopy(v->v, outv);
1289                                                 outv[3] = 1;
1290                                                 outc[0] = outc[1] = outc[2] = cl;
1291                                                 outc[3] = ca;
1292                                                 outst[0] = v->st[0];
1293                                                 outst[1] = v->st[1];
1294                                                 outuv[0] = v->uv[0];
1295                                                 outuv[1] = v->uv[1];
1296                                         }
1297                                 }
1298                         }
1299                 }
1300         }
1301 #else
1302         int i;
1303         float diff[3], ifog;
1304         surfvertex_t *v;
1305         surfvert_t *sv;
1306         surfmesh_t *mesh;
1307         rmeshinfo_t m;
1308
1309         memset(&m, 0, sizeof(m));
1310         if (currentrenderentity->effects & EF_ADDITIVE)
1311         {
1312                 m.transparent = true;
1313                 m.blendfunc1 = GL_SRC_ALPHA;
1314                 m.blendfunc2 = GL_ONE;
1315         }
1316         else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
1317         {
1318                 m.transparent = true;
1319                 m.blendfunc1 = GL_SRC_ALPHA;
1320                 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1321         }
1322         else
1323         {
1324                 m.transparent = false;
1325                 m.blendfunc1 = GL_ONE;
1326                 m.blendfunc2 = GL_ZERO;
1327         }
1328         m.cr = m.cg = m.cb = (float) (1 << lightscalebit);
1329         m.ca = currentrenderentity->alpha;
1330         m.tex[0] = R_GetTexture(surf->currenttexture->texture);
1331         m.tex[1] = R_GetTexture(surf->lightmaptexture);
1332         m.texcoordstep[0] = sizeof(surfvertex_t);
1333         m.texcoordstep[1] = sizeof(surfvertex_t);
1334         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1335         {
1336                 m.numtriangles = mesh->numtriangles;
1337                 m.numverts = mesh->numverts;
1338                 m.index = mesh->index;
1339                 m.texcoords[0] = &mesh->vertex->st[0];
1340                 m.texcoords[1] = &mesh->vertex->uv[0];
1341                 if (fogenabled)
1342                 {
1343                         m.color = &svert[0].c[0];
1344                         m.colorstep = sizeof(surfvert_t);
1345                         if (softwaretransform_complexity)
1346                         {
1347                                 m.vertex = &svert[0].v[0];
1348                                 m.vertexstep = sizeof(surfvert_t);
1349                                 for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
1350                                 {
1351                                         softwaretransform(v->v, sv->v);
1352                                         VectorSubtract(sv->v, r_origin, diff);
1353                                         ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
1354                                         sv->c[0] = m.cr * ifog;
1355                                         sv->c[1] = m.cg * ifog;
1356                                         sv->c[2] = m.cb * ifog;
1357                                         sv->c[3] = m.ca;
1358                                 }
1359                         }
1360                         else
1361                         {
1362                                 m.vertex = &mesh->vertex->v[0];
1363                                 m.vertexstep = sizeof(surfvertex_t);
1364                                 for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
1365                                 {
1366                                         VectorSubtract(v->v, r_origin, diff);
1367                                         ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
1368                                         sv->c[0] = m.cr * ifog;
1369                                         sv->c[1] = m.cg * ifog;
1370                                         sv->c[2] = m.cb * ifog;
1371                                         sv->c[3] = m.ca;
1372                                 }
1373                         }
1374                 }
1375                 else
1376                 {
1377                         if (softwaretransform_complexity)
1378                         {
1379                                 m.vertex = &svert[0].v[0];
1380                                 m.vertexstep = sizeof(surfvert_t);
1381                                 for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
1382                                         softwaretransform(v->v, sv->v);
1383                         }
1384                         else
1385                         {
1386                                 m.vertex = &mesh->vertex->v[0];
1387                                 m.vertexstep = sizeof(surfvertex_t);
1388                         }
1389                 }
1390                 R_Mesh_Draw(&m);
1391         }
1392 #endif
1393 }
1394
1395 static void RSurfShader_Wall_Pass_BaseTexture(msurface_t *surf)
1396 {
1397 #if USEMESHBUFFER
1398         int i;
1399         surfvertex_t *v;
1400         float *outv, *outc, *outst, cl, ca;
1401         surfmesh_t *mesh;
1402         rmeshbufferinfo_t m;
1403         memset(&m, 0, sizeof(m));
1404         m.transparent = false;
1405         m.blendfunc1 = GL_ONE;
1406         m.blendfunc2 = GL_ZERO;
1407         m.depthwrite = false;
1408         m.depthdisable = false;
1409         m.tex[0] = R_GetTexture(surf->currenttexture->texture);
1410         ca = currentrenderentity->alpha;
1411         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1412         {
1413                 m.numtriangles = mesh->numtriangles;
1414                 m.numverts = mesh->numverts;
1415
1416                 if (R_Mesh_Draw_GetBuffer(&m))
1417                 {
1418                         cl = (float) (1 << lightscalebit) * m.colorscale;
1419                         memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1420                         if (softwaretransform_complexity)
1421                         {
1422                                 for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2)
1423                                 {
1424                                         softwaretransform(v->v, outv);
1425                                         outv[3] = 1;
1426                                         outc[0] = outc[1] = outc[2] = cl;
1427                                         outc[3] = ca;
1428                                         outst[0] = v->st[0];
1429                                         outst[1] = v->st[1];
1430                                 }
1431                         }
1432                         else
1433                         {
1434                                 for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2)
1435                                 {
1436                                         VectorCopy(v->v, outv);
1437                                         outv[3] = 1;
1438                                         outc[0] = outc[1] = outc[2] = cl;
1439                                         outc[3] = ca;
1440                                         outst[0] = v->st[0];
1441                                         outst[1] = v->st[1];
1442                                 }
1443                         }
1444                 }
1445         }
1446 #else
1447         int i;
1448         surfvertex_t *v;
1449         surfvert_t *sv;
1450         surfmesh_t *mesh;
1451         rmeshinfo_t m;
1452
1453         memset(&m, 0, sizeof(m));
1454         m.transparent = false;
1455         m.blendfunc1 = GL_ONE;
1456         m.blendfunc2 = GL_ZERO;
1457         m.cr = m.cg = m.cb = (float) (1 << v_overbrightbits.integer);
1458         m.ca = 1;
1459         m.tex[0] = R_GetTexture(surf->currenttexture->texture);
1460         m.texcoordstep[0] = sizeof(surfvertex_t);
1461         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1462         {
1463                 m.numtriangles = mesh->numtriangles;
1464                 m.numverts = mesh->numverts;
1465                 m.index = mesh->index;
1466                 m.texcoords[0] = &mesh->vertex->st[0];
1467                 if (softwaretransform_complexity)
1468                 {
1469                         m.vertex = &svert[0].v[0];
1470                         m.vertexstep = sizeof(surfvert_t);
1471                         for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
1472                                 softwaretransform(v->v, sv->v);
1473                 }
1474                 else
1475                 {
1476                         m.vertex = &mesh->vertex->v[0];
1477                         m.vertexstep = sizeof(surfvertex_t);
1478                 }
1479                 R_Mesh_Draw(&m);
1480         }
1481 #endif
1482 }
1483
1484 static void RSurfShader_Wall_Pass_BaseLightmap(msurface_t *surf)
1485 {
1486 #if USEMESHBUFFER
1487         int i;
1488         surfvertex_t *v;
1489         float *outv, *outc, *outuv, cl, ca, diff[3];
1490         surfmesh_t *mesh;
1491         rmeshbufferinfo_t m;
1492         memset(&m, 0, sizeof(m));
1493         m.transparent = false;
1494         m.blendfunc1 = GL_ZERO;
1495         m.blendfunc2 = GL_SRC_COLOR;
1496         m.depthwrite = false;
1497         m.depthdisable = false;
1498         m.tex[0] = R_GetTexture(surf->lightmaptexture);
1499         ca = currentrenderentity->alpha;
1500         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1501         {
1502                 m.numtriangles = mesh->numtriangles;
1503                 m.numverts = mesh->numverts;
1504
1505                 if (R_Mesh_Draw_GetBuffer(&m))
1506                 {
1507                         cl = (float) (1 << lightscalebit) * m.colorscale;
1508                         memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1509                         if (fogenabled)
1510                         {
1511                                 if (softwaretransform_complexity)
1512                                 {
1513                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outuv = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outuv += 2)
1514                                         {
1515                                                 softwaretransform(v->v, outv);
1516                                                 outv[3] = 1;
1517                                                 VectorSubtract(outv, r_origin, diff);
1518                                                 outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff)));
1519                                                 outc[3] = ca;
1520                                                 outuv[0] = v->uv[0];
1521                                                 outuv[1] = v->uv[1];
1522                                         }
1523                                 }
1524                                 else
1525                                 {
1526                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outuv = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outuv += 2)
1527                                         {
1528                                                 VectorCopy(v->v, outv);
1529                                                 outv[3] = 1;
1530                                                 VectorSubtract(outv, r_origin, diff);
1531                                                 outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff)));
1532                                                 outc[3] = ca;
1533                                                 outuv[0] = v->uv[0];
1534                                                 outuv[1] = v->uv[1];
1535                                         }
1536                                 }
1537                         }
1538                         else
1539                         {
1540                                 if (softwaretransform_complexity)
1541                                 {
1542                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outuv = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outuv += 2)
1543                                         {
1544                                                 softwaretransform(v->v, outv);
1545                                                 outv[3] = 1;
1546                                                 outc[0] = outc[1] = outc[2] = cl;
1547                                                 outc[3] = ca;
1548                                                 outuv[0] = v->uv[0];
1549                                                 outuv[1] = v->uv[1];
1550                                         }
1551                                 }
1552                                 else
1553                                 {
1554                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outuv = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outuv += 2)
1555                                         {
1556                                                 VectorCopy(v->v, outv);
1557                                                 outv[3] = 1;
1558                                                 outc[0] = outc[1] = outc[2] = cl;
1559                                                 outc[3] = ca;
1560                                                 outuv[0] = v->uv[0];
1561                                                 outuv[1] = v->uv[1];
1562                                         }
1563                                 }
1564                         }
1565                 }
1566         }
1567 #else
1568         int i;
1569         float diff[3], ifog;
1570         surfvertex_t *v;
1571         surfvert_t *sv;
1572         surfmesh_t *mesh;
1573         rmeshinfo_t m;
1574
1575         memset(&m, 0, sizeof(m));
1576         m.transparent = false;
1577         m.blendfunc1 = GL_ZERO;
1578         m.blendfunc2 = GL_SRC_COLOR;
1579         m.cr = m.cg = m.cb = (float) (1 << v_overbrightbits.integer);
1580         m.ca = 1;
1581         m.tex[0] = R_GetTexture(surf->lightmaptexture);
1582         m.texcoordstep[0] = sizeof(surfvertex_t);
1583         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1584         {
1585                 m.numtriangles = mesh->numtriangles;
1586                 m.numverts = mesh->numverts;
1587                 m.index = mesh->index;
1588                 m.texcoords[0] = &mesh->vertex->uv[0];
1589                 if (fogenabled)
1590                 {
1591                         m.color = &svert[0].c[0];
1592                         m.colorstep = sizeof(surfvert_t);
1593                         if (softwaretransform_complexity)
1594                         {
1595                                 m.vertex = &svert[0].v[0];
1596                                 m.vertexstep = sizeof(surfvert_t);
1597                                 for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
1598                                 {
1599                                         softwaretransform(v->v, sv->v);
1600                                         VectorSubtract(sv->v, r_origin, diff);
1601                                         ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
1602                                         sv->c[0] = m.cr * ifog;
1603                                         sv->c[1] = m.cg * ifog;
1604                                         sv->c[2] = m.cb * ifog;
1605                                         sv->c[3] = m.ca;
1606                                 }
1607                         }
1608                         else
1609                         {
1610                                 m.vertex = &mesh->vertex->v[0];
1611                                 m.vertexstep = sizeof(surfvertex_t);
1612                                 for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
1613                                 {
1614                                         VectorSubtract(v->v, r_origin, diff);
1615                                         ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
1616                                         sv->c[0] = m.cr * ifog;
1617                                         sv->c[1] = m.cg * ifog;
1618                                         sv->c[2] = m.cb * ifog;
1619                                         sv->c[3] = m.ca;
1620                                 }
1621                         }
1622                 }
1623                 else
1624                 {
1625                         if (softwaretransform_complexity)
1626                         {
1627                                 m.vertex = &svert[0].v[0];
1628                                 m.vertexstep = sizeof(surfvert_t);
1629                                 for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
1630                                         softwaretransform(v->v, sv->v);
1631                         }
1632                         else
1633                         {
1634                                 m.vertex = &mesh->vertex->v[0];
1635                                 m.vertexstep = sizeof(surfvertex_t);
1636                         }
1637                 }
1638                 R_Mesh_Draw(&m);
1639         }
1640 #endif
1641 }
1642
1643 static void RSurfShader_Wall_Pass_BaseVertex(msurface_t *surf)
1644 {
1645 #if USEMESHBUFFER
1646         int i, size3;
1647         surfvertex_t *v;
1648         float *outv, *outc, *outst, *outuv, cl, ca, diff[3];
1649         float base[3], scale, f;
1650         qbyte *lm;
1651         surfmesh_t *mesh;
1652         rmeshbufferinfo_t m;
1653         memset(&m, 0, sizeof(m));
1654         if (currentrenderentity->effects & EF_ADDITIVE)
1655         {
1656                 m.transparent = true;
1657                 m.blendfunc1 = GL_SRC_ALPHA;
1658                 m.blendfunc2 = GL_ONE;
1659         }
1660         else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
1661         {
1662                 m.transparent = true;
1663                 m.blendfunc1 = GL_SRC_ALPHA;
1664                 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1665         }
1666         else
1667         {
1668                 m.transparent = false;
1669                 m.blendfunc1 = GL_ONE;
1670                 m.blendfunc2 = GL_ZERO;
1671         }
1672         m.depthwrite = false;
1673         m.depthdisable = false;
1674         m.tex[0] = R_GetTexture(surf->currenttexture->texture);
1675
1676         size3 = ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3;
1677
1678         base[0] = base[1] = base[2] = currentrenderentity->effects & EF_FULLBRIGHT ? 2.0f : r_ambient.value * (1.0f / 64.0f);
1679
1680         ca = currentrenderentity->alpha;
1681         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1682         {
1683                 m.numtriangles = mesh->numtriangles;
1684                 m.numverts = mesh->numverts;
1685
1686                 if (R_Mesh_Draw_GetBuffer(&m))
1687                 {
1688                         cl = m.colorscale;
1689                         memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1690
1691                         if (currentrenderentity->effects & EF_FULLBRIGHT)
1692                         {
1693                                 if (softwaretransform_complexity)
1694                                 {
1695                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2)
1696                                         {
1697                                                 softwaretransform(v->v, outv);
1698                                                 outv[3] = 1;
1699                                                 VectorSubtract(outv, r_origin, diff);
1700                                                 outc[0] = outc[1] = outc[2] = 2.0f * cl * (1 - exp(fogdensity/DotProduct(diff, diff)));
1701                                                 outc[3] = ca;
1702                                                 outst[0] = v->st[0];
1703                                                 outst[1] = v->st[1];
1704                                         }
1705                                 }
1706                                 else
1707                                 {
1708                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2)
1709                                         {
1710                                                 VectorCopy(v->v, outv);
1711                                                 outv[3] = 1;
1712                                                 VectorSubtract(outv, r_origin, diff);
1713                                                 outc[0] = outc[1] = outc[2] = 2.0f * cl * (1 - exp(fogdensity/DotProduct(diff, diff)));
1714                                                 outc[3] = ca;
1715                                                 outst[0] = v->st[0];
1716                                                 outst[1] = v->st[1];
1717                                         }
1718                                 }
1719                         }
1720                         else
1721                         {
1722                                 if (softwaretransform_complexity)
1723                                 {
1724                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2)
1725                                         {
1726                                                 softwaretransform(v->v, outv);
1727                                                 outv[3] = 1;
1728                                                 VectorCopy(base, outc);
1729                                                 outc[3] = ca;
1730                                                 outst[0] = v->st[0];
1731                                                 outst[1] = v->st[1];
1732                                         }
1733                                 }
1734                                 else
1735                                 {
1736                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2)
1737                                         {
1738                                                 VectorCopy(v->v, outv);
1739                                                 outv[3] = 1;
1740                                                 VectorCopy(base, outc);
1741                                                 outc[3] = ca;
1742                                                 outst[0] = v->st[0];
1743                                                 outst[1] = v->st[1];
1744                                         }
1745                                 }
1746
1747                                 if (surf->dlightframe == r_framecount)
1748                                         RSurf_LightSeparate(surf->dlightbits, m.numverts, m.vertex, m.color);
1749
1750                                 for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color;i < m.numverts;i++, v++, outv += 4, outc += 4)
1751                                 {
1752                                         if (surf->styles[0] != 255)
1753                                         {
1754                                                 lm = surf->samples + v->lightmapoffset;
1755                                                 scale = d_lightstylevalue[surf->styles[0]] * (1.0f / 32768.0f);
1756                                                 VectorMA(outc, scale, lm, outc);
1757                                                 if (surf->styles[1] != 255)
1758                                                 {
1759                                                         lm += size3;
1760                                                         scale = d_lightstylevalue[surf->styles[1]] * (1.0f / 32768.0f);
1761                                                         VectorMA(outc, scale, lm, outc);
1762                                                         if (surf->styles[2] != 255)
1763                                                         {
1764                                                                 lm += size3;
1765                                                                 scale = d_lightstylevalue[surf->styles[2]] * (1.0f / 32768.0f);
1766                                                                 VectorMA(outc, scale, lm, outc);
1767                                                                 if (surf->styles[3] != 255)
1768                                                                 {
1769                                                                         lm += size3;
1770                                                                         scale = d_lightstylevalue[surf->styles[3]] * (1.0f / 32768.0f);
1771                                                                         VectorMA(outc, scale, lm, outc);
1772                                                                 }
1773                                                         }
1774                                                 }
1775                                         }
1776                                         if (fogenabled)
1777                                         {
1778                                                 VectorSubtract(outv, r_origin, diff);
1779                                                 f = cl * (1 - exp(fogdensity/DotProduct(diff, diff)));
1780                                                 VectorScale(outc, f, outc);
1781                                         }
1782                                         else
1783                                                 VectorScale(outc, cl, outc);
1784                                 }
1785                         }
1786                 }
1787         }
1788 #else
1789         int i, size3;
1790         float c[3], base[3], scale, diff[3], ifog;
1791         surfvertex_t *v;
1792         surfvert_t *sv;
1793         surfmesh_t *mesh;
1794         rmeshinfo_t m;
1795         qbyte *lm;
1796
1797         size3 = ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3;
1798
1799         base[0] = base[1] = base[2] = currentrenderentity->effects & EF_FULLBRIGHT ? 2.0f : r_ambient.value * (1.0f / 128.0f);
1800
1801         memset(&m, 0, sizeof(m));
1802         if (currentrenderentity->effects & EF_ADDITIVE)
1803         {
1804                 m.transparent = true;
1805                 m.blendfunc1 = GL_SRC_ALPHA;
1806                 m.blendfunc2 = GL_ONE;
1807         }
1808         else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
1809         {
1810                 m.transparent = true;
1811                 m.blendfunc1 = GL_SRC_ALPHA;
1812                 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1813         }
1814         else
1815         {
1816                 m.transparent = false;
1817                 m.blendfunc1 = GL_ONE;
1818                 m.blendfunc2 = GL_ZERO;
1819         }
1820         m.vertex = &svert[0].v[0];
1821         m.vertexstep = sizeof(surfvert_t);
1822         m.color = &svert[0].c[0];
1823         m.colorstep = sizeof(surfvert_t);
1824         m.tex[0] = R_GetTexture(surf->currenttexture->texture);
1825         m.texcoordstep[0] = sizeof(surfvertex_t);
1826         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1827         {
1828                 m.numtriangles = mesh->numtriangles;
1829                 m.numverts = mesh->numverts;
1830                 m.index = mesh->index;
1831                 m.texcoords[0] = &mesh->vertex->st[0];
1832                 for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
1833                 {
1834                         softwaretransform(v->v, sv->v);
1835                         VectorCopy(base, c);
1836                         if (surf->styles[0] != 255)
1837                         {
1838                                 lm = surf->samples + v->lightmapoffset;
1839                                 scale = d_lightstylevalue[surf->styles[0]] * (1.0f / 32768.0f);
1840                                 VectorMA(c, scale, lm, c);
1841                                 if (surf->styles[1] != 255)
1842                                 {
1843                                         lm += size3;
1844                                         scale = d_lightstylevalue[surf->styles[1]] * (1.0f / 32768.0f);
1845                                         VectorMA(c, scale, lm, c);
1846                                         if (surf->styles[2] != 255)
1847                                         {
1848                                                 lm += size3;
1849                                                 scale = d_lightstylevalue[surf->styles[2]] * (1.0f / 32768.0f);
1850                                                 VectorMA(c, scale, lm, c);
1851                                                 if (surf->styles[3] != 255)
1852                                                 {
1853                                                         lm += size3;
1854                                                         scale = d_lightstylevalue[surf->styles[3]] * (1.0f / 32768.0f);
1855                                                         VectorMA(c, scale, lm, c);
1856                                                 }
1857                                         }
1858                                 }
1859                         }
1860                         sv->c[0] = c[0];
1861                         sv->c[1] = c[1];
1862                         sv->c[2] = c[2];
1863                         sv->c[3] = currentrenderentity->alpha;
1864                 }
1865                 if (surf->dlightframe == r_framecount)
1866                         RSurf_Light(surf->dlightbits, m.numverts);
1867                 if (fogenabled)
1868                 {
1869                         for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
1870                         {
1871                                 VectorSubtract(sv->v, r_origin, diff);
1872                                 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
1873                                 sv->c[0] *= ifog;
1874                                 sv->c[1] *= ifog;
1875                                 sv->c[2] *= ifog;
1876                         }
1877                 }
1878                 R_Mesh_Draw(&m);
1879         }
1880 #endif
1881 }
1882
1883 static void RSurfShader_Wall_Pass_BaseFullbright(msurface_t *surf)
1884 {
1885 #if USEMESHBUFFER
1886         int i;
1887         surfvertex_t *v;
1888         float *outv, *outc, *outst, cl, ca, diff[3];
1889         surfmesh_t *mesh;
1890         rmeshbufferinfo_t m;
1891         memset(&m, 0, sizeof(m));
1892         if (currentrenderentity->effects & EF_ADDITIVE)
1893         {
1894                 m.transparent = true;
1895                 m.blendfunc1 = GL_SRC_ALPHA;
1896                 m.blendfunc2 = GL_ONE;
1897         }
1898         else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
1899         {
1900                 m.transparent = true;
1901                 m.blendfunc1 = GL_SRC_ALPHA;
1902                 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1903         }
1904         else
1905         {
1906                 m.transparent = false;
1907                 m.blendfunc1 = GL_ONE;
1908                 m.blendfunc2 = GL_ZERO;
1909         }
1910         m.depthwrite = false;
1911         m.depthdisable = false;
1912         m.tex[0] = R_GetTexture(surf->currenttexture->texture);
1913         ca = currentrenderentity->alpha;
1914         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
1915         {
1916                 m.numtriangles = mesh->numtriangles;
1917                 m.numverts = mesh->numverts;
1918
1919                 if (R_Mesh_Draw_GetBuffer(&m))
1920                 {
1921                         cl = m.colorscale;
1922                         memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
1923                         if (fogenabled)
1924                         {
1925                                 if (softwaretransform_complexity)
1926                                 {
1927                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2)
1928                                         {
1929                                                 softwaretransform(v->v, outv);
1930                                                 outv[3] = 1;
1931                                                 VectorSubtract(outv, r_origin, diff);
1932                                                 outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff)));
1933                                                 outc[3] = ca;
1934                                                 outst[0] = v->st[0];
1935                                                 outst[1] = v->st[1];
1936                                         }
1937                                 }
1938                                 else
1939                                 {
1940                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2)
1941                                         {
1942                                                 VectorCopy(v->v, outv);
1943                                                 outv[3] = 1;
1944                                                 VectorSubtract(outv, r_origin, diff);
1945                                                 outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff)));
1946                                                 outc[3] = ca;
1947                                                 outst[0] = v->st[0];
1948                                                 outst[1] = v->st[1];
1949                                         }
1950                                 }
1951                         }
1952                         else
1953                         {
1954                                 if (softwaretransform_complexity)
1955                                 {
1956                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2)
1957                                         {
1958                                                 softwaretransform(v->v, outv);
1959                                                 outv[3] = 1;
1960                                                 outc[0] = outc[1] = outc[2] = cl;
1961                                                 outc[3] = ca;
1962                                                 outst[0] = v->st[0];
1963                                                 outst[1] = v->st[1];
1964                                         }
1965                                 }
1966                                 else
1967                                 {
1968                                         for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2)
1969                                         {
1970                                                 VectorCopy(v->v, outv);
1971                                                 outv[3] = 1;
1972                                                 outc[0] = outc[1] = outc[2] = cl;
1973                                                 outc[3] = ca;
1974                                                 outst[0] = v->st[0];
1975                                                 outst[1] = v->st[1];
1976                                         }
1977                                 }
1978                         }
1979                 }
1980         }
1981 #else
1982         int i;
1983         float diff[3], ifog;
1984         surfvertex_t *v;
1985         surfvert_t *sv;
1986         surfmesh_t *mesh;
1987         rmeshinfo_t m;
1988
1989         memset(&m, 0, sizeof(m));
1990         if (currentrenderentity->effects & EF_ADDITIVE)
1991         {
1992                 m.transparent = true;
1993                 m.blendfunc1 = GL_SRC_ALPHA;
1994                 m.blendfunc2 = GL_ONE;
1995         }
1996         else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
1997         {
1998                 m.transparent = true;
1999                 m.blendfunc1 = GL_SRC_ALPHA;
2000                 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2001         }
2002         else
2003         {
2004                 m.transparent = false;
2005                 m.blendfunc1 = GL_ONE;
2006                 m.blendfunc2 = GL_ZERO;
2007         }
2008         m.vertex = &svert[0].v[0];
2009         m.vertexstep = sizeof(surfvert_t);
2010         m.tex[0] = R_GetTexture(surf->currenttexture->texture);
2011         m.texcoordstep[0] = sizeof(surfvertex_t);
2012         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
2013         {
2014                 m.numtriangles = mesh->numtriangles;
2015                 m.numverts = mesh->numverts;
2016                 m.index = mesh->index;
2017                 m.texcoords[0] = &mesh->vertex->st[0];
2018                 if (fogenabled)
2019                 {
2020                         m.color = &svert[0].c[0];
2021                         m.colorstep = sizeof(surfvert_t);
2022                         for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
2023                         {
2024                                 softwaretransform(v->v, sv->v);
2025                                 VectorSubtract(sv->v, r_origin, diff);
2026                                 ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
2027                                 sv->c[0] = ifog;
2028                                 sv->c[1] = ifog;
2029                                 sv->c[2] = ifog;
2030                                 sv->c[3] = currentrenderentity->alpha;
2031                         }
2032                 }
2033                 else
2034                 {
2035                         m.cr = m.cg = m.cb = 1;
2036                         m.ca = currentrenderentity->alpha;
2037                         for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
2038                                 softwaretransform(v->v, sv->v);
2039                 }
2040                 R_Mesh_Draw(&m);
2041         }
2042 #endif
2043 }
2044
2045 static void RSurfShader_Wall_Pass_Light(msurface_t *surf)
2046 {
2047 #if USEMESHBUFFER
2048         int i;
2049         surfvertex_t *v;
2050         float *outv, *outc, *outst, *outuv, cl, ca, diff[3], f;
2051         surfmesh_t *mesh;
2052         rmeshbufferinfo_t m;
2053
2054         if (surf->dlightframe != r_framecount)
2055                 return;
2056         if (currentrenderentity->effects & EF_FULLBRIGHT)
2057                 return;
2058
2059         memset(&m, 0, sizeof(m));
2060         if (currentrenderentity->effects & EF_ADDITIVE)
2061         {
2062                 m.transparent = true;
2063                 m.blendfunc1 = GL_SRC_ALPHA;
2064                 m.blendfunc2 = GL_ONE;
2065         }
2066         else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
2067         {
2068                 m.transparent = true;
2069                 m.blendfunc1 = GL_SRC_ALPHA;
2070                 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2071         }
2072         else
2073         {
2074                 m.transparent = false;
2075                 m.blendfunc1 = GL_ONE;
2076                 m.blendfunc2 = GL_ZERO;
2077         }
2078         m.depthwrite = false;
2079         m.depthdisable = false;
2080         m.tex[0] = R_GetTexture(surf->currenttexture->texture);
2081         ca = currentrenderentity->alpha;
2082         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
2083         {
2084                 if (RSurf_LightCheck(surf->dlightbits, mesh))
2085                 {
2086                         m.numtriangles = mesh->numtriangles;
2087                         m.numverts = mesh->numverts;
2088
2089                         if (R_Mesh_Draw_GetBuffer(&m))
2090                         {
2091                                 cl = m.colorscale;
2092                                 memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
2093                                 for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0], outuv = m.texcoords[1];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2, outuv += 2)
2094                                 {
2095                                         softwaretransform(v->v, outv);
2096                                         outv[3] = 1;
2097                                         VectorClear(outc);
2098                                         outc[3] = ca;
2099                                         outst[0] = v->st[0];
2100                                         outst[1] = v->st[1];
2101                                 }
2102                                 RSurf_LightSeparate(surf->dlightbits, m.numverts, m.vertex, m.color);
2103                                 if (fogenabled)
2104                                 {
2105                                         for (i = 0, outv = m.vertex, outc = m.color;i < m.numverts;i++, outv += 4, outc += 4)
2106                                         {
2107                                                 VectorSubtract(outv, r_origin, diff);
2108                                                 f = cl * (1 - exp(fogdensity/DotProduct(diff, diff)));
2109                                                 VectorScale(outc, f, outc);
2110                                         }
2111                                 }
2112                                 else if (cl != 1)
2113                                         for (i = 0, outc = m.color;i < m.numverts;i++, outc += 4)
2114                                                 VectorScale(outc, cl, outc);
2115                         }
2116                 }
2117         }
2118 #else
2119         int i;
2120         float diff[3], ifog;
2121         surfvertex_t *v;
2122         surfvert_t *sv;
2123         surfmesh_t *mesh;
2124         rmeshinfo_t m;
2125
2126         memset(&m, 0, sizeof(m));
2127         if (currentrenderentity->effects & EF_ADDITIVE)
2128                 m.transparent = true;
2129         else if (surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1)
2130                 m.transparent = true;
2131         else
2132                 m.transparent = false;
2133         m.blendfunc1 = GL_SRC_ALPHA;
2134         m.blendfunc2 = GL_ONE;
2135         m.vertex = &svert[0].v[0];
2136         m.vertexstep = sizeof(surfvert_t);
2137         m.color = &svert[0].c[0];
2138         m.colorstep = sizeof(surfvert_t);
2139         m.tex[0] = R_GetTexture(surf->currenttexture->texture);
2140         m.texcoordstep[0] = sizeof(surfvertex_t);
2141         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
2142         {
2143                 m.numtriangles = mesh->numtriangles;
2144                 m.numverts = mesh->numverts;
2145                 m.index = mesh->index;
2146                 m.texcoords[0] = &mesh->vertex->st[0];
2147                 for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
2148                 {
2149                         softwaretransform(v->v, sv->v);
2150                         sv->c[0] = 0;
2151                         sv->c[1] = 0;
2152                         sv->c[2] = 0;
2153                         sv->c[3] = currentrenderentity->alpha;
2154                 }
2155                 if (RSurf_Light(surf->dlightbits, m.numverts))
2156                 {
2157                         if (fogenabled)
2158                         {
2159                                 for (i = 0, sv = svert;i < m.numverts;i++, sv++)
2160                                 {
2161                                         VectorSubtract(sv->v, r_origin, diff);
2162                                         ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
2163                                         sv->c[0] *= ifog;
2164                                         sv->c[1] *= ifog;
2165                                         sv->c[2] *= ifog;
2166                                 }
2167                         }
2168                         R_Mesh_Draw(&m);
2169                 }
2170         }
2171 #endif
2172 }
2173
2174 static void RSurfShader_Wall_Pass_Glow(msurface_t *surf)
2175 {
2176 #if USEMESHBUFFER
2177         int i;
2178         surfvertex_t *v;
2179         float *outv, *outc, *outst, cl, ca, diff[3];
2180         surfmesh_t *mesh;
2181         rmeshbufferinfo_t m;
2182         memset(&m, 0, sizeof(m));
2183         m.transparent = currentrenderentity->effects & EF_ADDITIVE || surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1;
2184         m.blendfunc1 = GL_SRC_ALPHA;
2185         m.blendfunc2 = GL_ONE;
2186         m.tex[0] = R_GetTexture(surf->currenttexture->glowtexture);
2187         ca = currentrenderentity->alpha;
2188         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
2189         {
2190                 m.numtriangles = mesh->numtriangles;
2191                 m.numverts = mesh->numverts;
2192
2193                 if (R_Mesh_Draw_GetBuffer(&m))
2194                 {
2195                         cl = m.colorscale;
2196                         memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
2197                         if (fogenabled)
2198                         {
2199                                 for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2)
2200                                 {
2201                                         softwaretransform(v->v, outv);
2202                                         outv[3] = 1;
2203                                         VectorSubtract(outv, r_origin, diff);
2204                                         outc[0] = outc[1] = outc[2] = cl * (1 - exp(fogdensity/DotProduct(diff, diff)));
2205                                         outc[3] = ca;
2206                                         outst[0] = v->st[0];
2207                                         outst[1] = v->st[1];
2208                                 }
2209                         }
2210                         else
2211                         {
2212                                 for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2)
2213                                 {
2214                                         softwaretransform(v->v, outv);
2215                                         outv[3] = 1;
2216                                         outc[0] = outc[1] = outc[2] = cl;
2217                                         outc[3] = ca;
2218                                         outst[0] = v->st[0];
2219                                         outst[1] = v->st[1];
2220                                 }
2221                         }
2222                 }
2223         }
2224 #else
2225         int i;
2226         float diff[3], ifog;
2227         surfvertex_t *v;
2228         surfvert_t *sv;
2229         surfmesh_t *mesh;
2230         rmeshinfo_t m;
2231
2232         memset(&m, 0, sizeof(m));
2233         m.transparent = currentrenderentity->effects & EF_ADDITIVE || surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1;
2234         m.blendfunc1 = GL_SRC_ALPHA;
2235         m.blendfunc2 = GL_ONE;
2236         m.cr = 1;
2237         m.cg = 1;
2238         m.cb = 1;
2239         m.ca = currentrenderentity->alpha;
2240         m.tex[0] = R_GetTexture(surf->currenttexture->glowtexture);
2241         m.texcoordstep[0] = sizeof(surfvertex_t);
2242         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
2243         {
2244                 m.numtriangles = mesh->numtriangles;
2245                 m.numverts = mesh->numverts;
2246                 m.index = mesh->index;
2247                 m.texcoords[0] = &mesh->vertex->st[0];
2248                 if (fogenabled)
2249                 {
2250                         m.color = &svert[0].c[0];
2251                         m.colorstep = sizeof(surfvert_t);
2252                         if (softwaretransform_complexity)
2253                         {
2254                                 m.vertex = &svert[0].v[0];
2255                                 m.vertexstep = sizeof(surfvert_t);
2256                                 for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
2257                                 {
2258                                         softwaretransform(v->v, sv->v);
2259                                         VectorSubtract(sv->v, r_origin, diff);
2260                                         ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
2261                                         sv->c[0] = m.cr * ifog;
2262                                         sv->c[1] = m.cg * ifog;
2263                                         sv->c[2] = m.cb * ifog;
2264                                         sv->c[3] = m.ca;
2265                                 }
2266                         }
2267                         else
2268                         {
2269                                 m.vertex = &mesh->vertex->v[0];
2270                                 m.vertexstep = sizeof(surfvertex_t);
2271                                 for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
2272                                 {
2273                                         VectorSubtract(v->v, r_origin, diff);
2274                                         ifog = 1 - exp(fogdensity/DotProduct(diff, diff));
2275                                         sv->c[0] = m.cr * ifog;
2276                                         sv->c[1] = m.cg * ifog;
2277                                         sv->c[2] = m.cb * ifog;
2278                                         sv->c[3] = m.ca;
2279                                 }
2280                         }
2281                 }
2282                 else
2283                 {
2284                         if (softwaretransform_complexity)
2285                         {
2286                                 m.vertex = &svert[0].v[0];
2287                                 m.vertexstep = sizeof(surfvert_t);
2288                                 for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
2289                                         softwaretransform(v->v, sv->v);
2290                         }
2291                         else
2292                         {
2293                                 m.vertex = &mesh->vertex->v[0];
2294                                 m.vertexstep = sizeof(surfvertex_t);
2295                         }
2296                 }
2297                 R_Mesh_Draw(&m);
2298         }
2299 #endif
2300 }
2301
2302 static void RSurfShader_Wall_Pass_Fog(msurface_t *surf)
2303 {
2304 #if USEMESHBUFFER
2305         int i;
2306         surfvertex_t *v;
2307         float *outv, *outc, *outst, cl, ca, diff[3], f;
2308         surfmesh_t *mesh;
2309         rmeshbufferinfo_t m;
2310         memset(&m, 0, sizeof(m));
2311         m.transparent = currentrenderentity->effects & EF_ADDITIVE || surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1;
2312         m.blendfunc1 = GL_SRC_ALPHA;
2313         m.blendfunc2 = GL_ONE;
2314         ca = currentrenderentity->alpha;
2315         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
2316         {
2317                 m.numtriangles = mesh->numtriangles;
2318                 m.numverts = mesh->numverts;
2319
2320                 if (R_Mesh_Draw_GetBuffer(&m))
2321                 {
2322                         cl = m.colorscale;
2323                         memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
2324                         if (softwaretransform_complexity)
2325                         {
2326                                 for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2)
2327                                 {
2328                                         softwaretransform(v->v, outv);
2329                                         outv[3] = 1;
2330                                         VectorSubtract(outv, r_origin, diff);
2331                                         f = cl * exp(fogdensity/DotProduct(diff, diff));
2332                                         VectorScale(fogcolor, f, outc);
2333                                         outc[3] = ca;
2334                                         outst[0] = v->st[0];
2335                                         outst[1] = v->st[1];
2336                                 }
2337                         }
2338                         else
2339                         {
2340                                 for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2)
2341                                 {
2342                                         VectorCopy(v->v, outv);
2343                                         outv[3] = 1;
2344                                         VectorSubtract(outv, r_origin, diff);
2345                                         VectorSubtract(outv, r_origin, diff);
2346                                         f = cl * exp(fogdensity/DotProduct(diff, diff));
2347                                         VectorScale(fogcolor, f, outc);
2348                                         outc[3] = ca;
2349                                         outst[0] = v->st[0];
2350                                         outst[1] = v->st[1];
2351                                 }
2352                         }
2353                 }
2354         }
2355 #else
2356         int i;
2357         surfvertex_t *v;
2358         surfvert_t *sv;
2359         rmeshinfo_t m;
2360         surfmesh_t *mesh;
2361         vec3_t diff;
2362
2363         memset(&m, 0, sizeof(m));
2364         m.transparent = currentrenderentity->effects & EF_ADDITIVE || surf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1;
2365         m.blendfunc1 = GL_SRC_ALPHA;
2366         m.blendfunc2 = GL_ONE;
2367         m.color = &svert[0].c[0];
2368         m.colorstep = sizeof(surfvert_t);
2369         m.tex[0] = R_GetTexture(surf->currenttexture->fogtexture);
2370         m.texcoordstep[0] = sizeof(surfvertex_t);
2371         for (mesh = surf->mesh;mesh;mesh = mesh->chain)
2372         {
2373                 m.numtriangles = mesh->numtriangles;
2374                 m.numverts = mesh->numverts;
2375                 m.index = mesh->index;
2376                 m.texcoords[0] = &mesh->vertex->st[0];
2377                 if (softwaretransform_complexity)
2378                 {
2379                         m.vertex = &svert[0].v[0];
2380                         m.vertexstep = sizeof(surfvert_t);
2381                         for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
2382                         {
2383                                 softwaretransform(v->v, sv->v);
2384                                 VectorSubtract(sv->v, r_origin, diff);
2385                                 sv->c[0] = fogcolor[0];
2386                                 sv->c[1] = fogcolor[1];
2387                                 sv->c[2] = fogcolor[2];
2388                                 sv->c[3] = currentrenderentity->alpha * exp(fogdensity/DotProduct(diff,diff));
2389                         }
2390                 }
2391                 else
2392                 {
2393                         m.vertex = &mesh->vertex->v[0];
2394                         m.vertexstep = sizeof(surfvertex_t);
2395                         for (i = 0, sv = svert, v = mesh->vertex;i < m.numverts;i++, sv++, v++)
2396                         {
2397                                 VectorSubtract(v->v, r_origin, diff);
2398                                 sv->c[0] = fogcolor[0];
2399                                 sv->c[1] = fogcolor[1];
2400                                 sv->c[2] = fogcolor[2];
2401                                 sv->c[3] = currentrenderentity->alpha * exp(fogdensity/DotProduct(diff,diff));
2402                         }
2403                 }
2404                 R_Mesh_Draw(&m);
2405         }
2406 #endif
2407 }
2408
2409 static void RSurfShader_Wall_Fullbright(msurface_t *firstsurf)
2410 {
2411         msurface_t *surf;
2412         for (surf = firstsurf;surf;surf = surf->chain)
2413         {
2414                 c_brush_polys++;
2415                 RSurfShader_Wall_Pass_BaseFullbright(surf);
2416         }
2417         for (surf = firstsurf;surf;surf = surf->chain)
2418                 if (surf->currenttexture->glowtexture)
2419                         RSurfShader_Wall_Pass_Glow(surf);
2420         if (fogenabled)
2421                 for (surf = firstsurf;surf;surf = surf->chain)
2422                         RSurfShader_Wall_Pass_Fog(surf);
2423 }
2424
2425 static void RSurfShader_Wall_Vertex(msurface_t *firstsurf)
2426 {
2427         msurface_t *surf;
2428         for (surf = firstsurf;surf;surf = surf->chain)
2429         {
2430                 c_brush_polys++;
2431                 RSurfShader_Wall_Pass_BaseVertex(surf);
2432         }
2433         for (surf = firstsurf;surf;surf = surf->chain)
2434                 if (surf->currenttexture->glowtexture)
2435                         RSurfShader_Wall_Pass_Glow(surf);
2436         if (fogenabled)
2437                 for (surf = firstsurf;surf;surf = surf->chain)
2438                         RSurfShader_Wall_Pass_Fog(surf);
2439 }
2440
2441 static void RSurfShader_Wall_Lightmap(msurface_t *firstsurf)
2442 {
2443         msurface_t *surf;
2444         if (r_vertexsurfaces.integer)
2445         {
2446                 for (surf = firstsurf;surf;surf = surf->chain)
2447                 {
2448                         c_brush_polys++;
2449                         RSurfShader_Wall_Pass_BaseVertex(surf);
2450                 }
2451                 for (surf = firstsurf;surf;surf = surf->chain)
2452                         if (surf->currenttexture->glowtexture)
2453                                 RSurfShader_Wall_Pass_Glow(surf);
2454                 if (fogenabled)
2455                         for (surf = firstsurf;surf;surf = surf->chain)
2456                                 RSurfShader_Wall_Pass_Fog(surf);
2457         }
2458         else if (r_multitexture.integer)
2459         {
2460                 if (r_dlightmap.integer)
2461                 {
2462                         for (surf = firstsurf;surf;surf = surf->chain)
2463                         {
2464                                 c_brush_polys++;
2465                                 RSurfShader_Wall_Pass_BaseMTex(surf);
2466                         }
2467                         for (surf = firstsurf;surf;surf = surf->chain)
2468                                 if (surf->currenttexture->glowtexture)
2469                                         RSurfShader_Wall_Pass_Glow(surf);
2470                         if (fogenabled)
2471                                 for (surf = firstsurf;surf;surf = surf->chain)
2472                                         RSurfShader_Wall_Pass_Fog(surf);
2473                 }
2474                 else
2475                 {
2476                         for (surf = firstsurf;surf;surf = surf->chain)
2477                         {
2478                                 c_brush_polys++;
2479                                 RSurfShader_Wall_Pass_BaseMTex(surf);
2480                         }
2481                         for (surf = firstsurf;surf;surf = surf->chain)
2482                                 if (surf->dlightframe == r_framecount)
2483                                         RSurfShader_Wall_Pass_Light(surf);
2484                         for (surf = firstsurf;surf;surf = surf->chain)
2485                                 if (surf->currenttexture->glowtexture)
2486                                         RSurfShader_Wall_Pass_Glow(surf);
2487                         if (fogenabled)
2488                                 for (surf = firstsurf;surf;surf = surf->chain)
2489                                         RSurfShader_Wall_Pass_Fog(surf);
2490                 }
2491         }
2492         else if (firstsurf->currenttexture->fogtexture != NULL || currentrenderentity->alpha != 1 || currentrenderentity->effects & EF_ADDITIVE)
2493         {
2494                 for (surf = firstsurf;surf;surf = surf->chain)
2495                 {
2496                         c_brush_polys++;
2497                         RSurfShader_Wall_Pass_BaseVertex(surf);
2498                 }
2499                 for (surf = firstsurf;surf;surf = surf->chain)
2500                         if (surf->currenttexture->glowtexture)
2501                                 RSurfShader_Wall_Pass_Glow(surf);
2502                 if (fogenabled)
2503                         for (surf = firstsurf;surf;surf = surf->chain)
2504                                 RSurfShader_Wall_Pass_Fog(surf);
2505         }
2506         else
2507         {
2508                 if (r_dlightmap.integer)
2509                 {
2510                         for (surf = firstsurf;surf;surf = surf->chain)
2511                         {
2512                                 c_brush_polys++;
2513                                 RSurfShader_Wall_Pass_BaseTexture(surf);
2514                         }
2515                         for (surf = firstsurf;surf;surf = surf->chain)
2516                                 RSurfShader_Wall_Pass_BaseLightmap(surf);
2517                         for (surf = firstsurf;surf;surf = surf->chain)
2518                                 if (surf->currenttexture->glowtexture)
2519                                         RSurfShader_Wall_Pass_Glow(surf);
2520                         if (fogenabled)
2521                                 for (surf = firstsurf;surf;surf = surf->chain)
2522                                         RSurfShader_Wall_Pass_Fog(surf);
2523                 }
2524                 else
2525                 {
2526                         for (surf = firstsurf;surf;surf = surf->chain)
2527                         {
2528                                 c_brush_polys++;
2529                                 RSurfShader_Wall_Pass_BaseTexture(surf);
2530                         }
2531                         for (surf = firstsurf;surf;surf = surf->chain)
2532                                 RSurfShader_Wall_Pass_BaseLightmap(surf);
2533                         for (surf = firstsurf;surf;surf = surf->chain)
2534                                 if (surf->dlightframe == r_framecount)
2535                                         RSurfShader_Wall_Pass_Light(surf);
2536                         for (surf = firstsurf;surf;surf = surf->chain)
2537                                 if (surf->currenttexture->glowtexture)
2538                                         RSurfShader_Wall_Pass_Glow(surf);
2539                         if (fogenabled)
2540                                 for (surf = firstsurf;surf;surf = surf->chain)
2541                                         RSurfShader_Wall_Pass_Fog(surf);
2542                 }
2543         }
2544 }
2545
2546 /*
2547 =============================================================
2548
2549         WORLD MODEL
2550
2551 =============================================================
2552 */
2553
2554 static void R_SolidWorldNode (void)
2555 {
2556         if (r_viewleaf->contents != CONTENTS_SOLID)
2557         {
2558                 int portalstack;
2559                 mportal_t *p, *pstack[8192];
2560                 msurface_t *surf, **mark, **endmark;
2561                 mleaf_t *leaf;
2562                 // LordHavoc: portal-passage worldnode; follows portals leading
2563                 // outward from viewleaf, if a portal leads offscreen it is not
2564                 // followed, in indoor maps this can often cull a great deal of
2565                 // geometry away when pvs data is not present (useful with pvs as well)
2566
2567                 leaf = r_viewleaf;
2568                 leaf->worldnodeframe = r_framecount;
2569                 portalstack = 0;
2570         loc0:
2571                 c_leafs++;
2572
2573                 leaf->visframe = r_framecount;
2574
2575                 if (leaf->nummarksurfaces)
2576                 {
2577                         mark = leaf->firstmarksurface;
2578                         endmark = mark + leaf->nummarksurfaces;
2579                         do
2580                         {
2581                                 surf = *mark++;
2582                                 // make sure surfaces are only processed once
2583                                 if (surf->worldnodeframe == r_framecount)
2584                                         continue;
2585                                 surf->worldnodeframe = r_framecount;
2586                                 if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
2587                                 {
2588                                         if (surf->flags & SURF_PLANEBACK)
2589                                                 surf->visframe = r_framecount;
2590                                 }
2591                                 else
2592                                 {
2593                                         if (!(surf->flags & SURF_PLANEBACK))
2594                                                 surf->visframe = r_framecount;
2595                                 }
2596                         }
2597                         while (mark < endmark);
2598                 }
2599
2600                 // follow portals into other leafs
2601                 p = leaf->portals;
2602                 for (;p;p = p->next)
2603                 {
2604                         if (DotProduct(r_origin, p->plane.normal) < p->plane.dist)
2605                         {
2606                                 leaf = p->past;
2607                                 if (leaf->worldnodeframe != r_framecount)
2608                                 {
2609                                         leaf->worldnodeframe = r_framecount;
2610                                         if (leaf->contents != CONTENTS_SOLID)
2611                                         {
2612                                                 if (R_NotCulledBox(leaf->mins, leaf->maxs))
2613                                                 {
2614                                                         p->visframe = r_framecount;
2615                                                         pstack[portalstack++] = p;
2616                                                         goto loc0;
2617
2618         loc1:
2619                                                         p = pstack[--portalstack];
2620                                                 }
2621                                         }
2622                                 }
2623                         }
2624                 }
2625
2626                 if (portalstack)
2627                         goto loc1;
2628         }
2629         else
2630         {
2631                 mnode_t *nodestack[8192], *node = cl.worldmodel->nodes;
2632                 int nodestackpos = 0;
2633                 // LordHavoc: recursive descending worldnode; if portals are not
2634                 // available, this is a good last resort, can cull large amounts of
2635                 // geometry, but is more time consuming than portal-passage and renders
2636                 // things behind walls
2637
2638 loc2:
2639                 if (R_NotCulledBox(node->mins, node->maxs))
2640                 {
2641                         if (node->numsurfaces)
2642                         {
2643                                 msurface_t *surf = cl.worldmodel->surfaces + node->firstsurface, *surfend = surf + node->numsurfaces;
2644                                 if (PlaneDiff (r_origin, node->plane) < 0)
2645                                 {
2646                                         for (;surf < surfend;surf++)
2647                                         {
2648                                                 if (surf->flags & SURF_PLANEBACK)
2649                                                         surf->visframe = r_framecount;
2650                                         }
2651                                 }
2652                                 else
2653                                 {
2654                                         for (;surf < surfend;surf++)
2655                                         {
2656                                                 if (!(surf->flags & SURF_PLANEBACK))
2657                                                         surf->visframe = r_framecount;
2658                                         }
2659                                 }
2660                         }
2661
2662                         // recurse down the children
2663                         if (node->children[0]->contents >= 0)
2664                         {
2665                                 if (node->children[1]->contents >= 0)
2666                                 {
2667                                         if (nodestackpos < 8192)
2668                                                 nodestack[nodestackpos++] = node->children[1];
2669                                         node = node->children[0];
2670                                         goto loc2;
2671                                 }
2672                                 else
2673                                         ((mleaf_t *)node->children[1])->visframe = r_framecount;
2674                                 node = node->children[0];
2675                                 goto loc2;
2676                         }
2677                         else
2678                         {
2679                                 ((mleaf_t *)node->children[0])->visframe = r_framecount;
2680                                 if (node->children[1]->contents >= 0)
2681                                 {
2682                                         node = node->children[1];
2683                                         goto loc2;
2684                                 }
2685                                 else if (nodestackpos > 0)
2686                                 {
2687                                         ((mleaf_t *)node->children[1])->visframe = r_framecount;
2688                                         node = nodestack[--nodestackpos];
2689                                         goto loc2;
2690                                 }
2691                         }
2692                 }
2693                 else if (nodestackpos > 0)
2694                 {
2695                         node = nodestack[--nodestackpos];
2696                         goto loc2;
2697                 }
2698         }
2699 }
2700
2701 static int r_portalframecount = 0;
2702
2703 static void R_PVSWorldNode()
2704 {
2705         int portalstack, i;
2706         mportal_t *p, *pstack[8192];
2707         msurface_t *surf, **mark, **endmark;
2708         mleaf_t *leaf;
2709         qbyte *worldvis;
2710
2711         worldvis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
2712
2713         leaf = r_viewleaf;
2714         leaf->worldnodeframe = r_framecount;
2715         portalstack = 0;
2716 loc0:
2717         c_leafs++;
2718
2719         leaf->visframe = r_framecount;
2720
2721         if (leaf->nummarksurfaces)
2722         {
2723                 mark = leaf->firstmarksurface;
2724                 endmark = mark + leaf->nummarksurfaces;
2725                 do
2726                 {
2727                         surf = *mark++;
2728                         // make sure surfaces are only processed once
2729                         if (surf->worldnodeframe == r_framecount)
2730                                 continue;
2731                         surf->worldnodeframe = r_framecount;
2732                         if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
2733                         {
2734                                 if (surf->flags & SURF_PLANEBACK)
2735                                         surf->visframe = r_framecount;
2736                         }
2737                         else
2738                         {
2739                                 if (!(surf->flags & SURF_PLANEBACK))
2740                                         surf->visframe = r_framecount;
2741                         }
2742                 }
2743                 while (mark < endmark);
2744         }
2745
2746         // follow portals into other leafs
2747         for (p = leaf->portals;p;p = p->next)
2748         {
2749                 if (DotProduct(r_origin, p->plane.normal) < p->plane.dist)
2750                 {
2751                         leaf = p->past;
2752                         if (leaf->worldnodeframe != r_framecount)
2753                         {
2754                                 leaf->worldnodeframe = r_framecount;
2755                                 if (leaf->contents != CONTENTS_SOLID)
2756                                 {
2757                                         i = (leaf - cl.worldmodel->leafs) - 1;
2758                                         if (worldvis[i>>3] & (1<<(i&7)))
2759                                         {
2760                                                 if (R_NotCulledBox(leaf->mins, leaf->maxs))
2761                                                 {
2762                                                         pstack[portalstack++] = p;
2763                                                         goto loc0;
2764
2765 loc1:
2766                                                         p = pstack[--portalstack];
2767                                                 }
2768                                         }
2769                                 }
2770                         }
2771                 }
2772         }
2773
2774         if (portalstack)
2775                 goto loc1;
2776 }
2777
2778 Cshader_t Cshader_wall_vertex = {{NULL, RSurfShader_Wall_Vertex}, NULL};
2779 Cshader_t Cshader_wall_lightmap = {{NULL, RSurfShader_Wall_Lightmap}, NULL};
2780 Cshader_t Cshader_wall_fullbright = {{NULL, RSurfShader_Wall_Fullbright}, NULL};
2781 Cshader_t Cshader_water = {{NULL, RSurfShader_Water}, NULL};
2782 Cshader_t Cshader_sky = {{RSurfShader_Sky, NULL}, NULL};
2783
2784 int Cshader_count = 5;
2785 Cshader_t *Cshaders[5] =
2786 {
2787         &Cshader_wall_vertex,
2788         &Cshader_wall_lightmap,
2789         &Cshader_wall_fullbright,
2790         &Cshader_water,
2791         &Cshader_sky
2792 };
2793
2794 void R_PrepareSurfaces(void)
2795 {
2796         int i, alttextures, texframe, framecount;
2797         texture_t *t;
2798         model_t *model;
2799         msurface_t *surf;
2800
2801         for (i = 0;i < Cshader_count;i++)
2802                 Cshaders[i]->chain = NULL;
2803
2804         model = currentrenderentity->model;
2805         alttextures = currentrenderentity->frame != 0;
2806         texframe = (int)(cl.time * 5.0f);
2807
2808         for (i = 0;i < model->nummodelsurfaces;i++)
2809         {
2810                 surf = model->modelsortedsurfaces[i];
2811                 if (surf->visframe == r_framecount)
2812                 {
2813                         if (surf->insertframe != r_framecount)
2814                         {
2815                                 surf->insertframe = r_framecount;
2816                                 c_faces++;
2817                                 t = surf->texinfo->texture;
2818                                 if (t->animated)
2819                                 {
2820  &nbs