2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // r_surf.c: surface-related refresh code
25 #define MAX_LIGHTMAP_SIZE 256
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
30 static qbyte templight[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*4];
32 cvar_t r_ambient = {0, "r_ambient", "0"};
33 cvar_t r_drawportals = {0, "r_drawportals", "0"};
34 cvar_t r_testvis = {0, "r_testvis", "0"};
35 cvar_t r_floatbuildlightmap = {0, "r_floatbuildlightmap", "0"};
36 cvar_t r_detailtextures = {CVAR_SAVE, "r_detailtextures", "1"};
37 cvar_t r_surfaceworldnode = {0, "r_surfaceworldnode", "0"};
38 cvar_t r_drawcollisionbrushes_polygonfactor = {0, "r_drawcollisionbrushes_polygonfactor", "-1"};
39 cvar_t r_drawcollisionbrushes_polygonoffset = {0, "r_drawcollisionbrushes_polygonoffset", "0"};
40 cvar_t r_q3bsp_renderskydepth = {0, "r_q3bsp_renderskydepth", "0"};
41 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
43 // flag arrays used for visibility checking on world model
44 // (all other entities have no per-surface/per-leaf visibility checks)
45 // TODO: dynamic resize according to r_refdef.worldmodel->brush.num_clusters
46 qbyte r_pvsbits[(32768+7)>>3];
47 // TODO: dynamic resize according to r_refdef.worldmodel->brush.num_leafs
48 qbyte r_worldleafvisible[32768];
49 // TODO: dynamic resize according to r_refdef.worldmodel->brush.num_surfaces
50 qbyte r_worldsurfacevisible[262144];
52 static int dlightdivtable[32768];
54 static int R_IntAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surface)
56 int sdtable[256], lnum, td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, smax3, red, green, blue, lit, dist2, impacts, impactt, subtract, k;
58 float dist, impact[3], local[3], planenormal[3], planedist;
63 smax = (surface->extents[0] >> 4) + 1;
64 tmax = (surface->extents[1] >> 4) + 1;
67 for (lnum = 0, light = r_dlight;lnum < r_numdlights;lnum++, light++)
69 if (!(surface->dlightbits[lnum >> 5] & (1 << (lnum & 31))))
70 continue; // not lit by this light
72 Matrix4x4_Transform(matrix, light->origin, local);
73 VectorCopy(surface->mesh.data_normal3f, planenormal);
74 planedist = DotProduct(surface->mesh.data_vertex3f, planenormal);
75 dist = DotProduct(local, planenormal) - planedist;
77 // for comparisons to minimum acceptable light
78 // compensate for LIGHTOFFSET
79 maxdist = (int) light->rtlight.lightmap_cullradius2 + LIGHTOFFSET;
86 VectorMA(local, -dist, planenormal, impact);
88 impacts = DotProduct (impact, surface->texinfo->vecs[0]) + surface->texinfo->vecs[0][3] - surface->texturemins[0];
89 impactt = DotProduct (impact, surface->texinfo->vecs[1]) + surface->texinfo->vecs[1][3] - surface->texturemins[1];
91 s = bound(0, impacts, smax * 16) - impacts;
92 t = bound(0, impactt, tmax * 16) - impactt;
93 i = s * s + t * t + dist2;
97 // reduce calculations
98 for (s = 0, i = impacts; s < smax; s++, i -= 16)
99 sdtable[s] = i * i + dist2;
101 maxdist3 = maxdist - dist2;
103 // convert to 8.8 blocklights format
104 red = light->rtlight.lightmap_light[0] * (1.0f / 128.0f);
105 green = light->rtlight.lightmap_light[1] * (1.0f / 128.0f);
106 blue = light->rtlight.lightmap_light[2] * (1.0f / 128.0f);
107 subtract = (int) (light->rtlight.lightmap_subtract * 4194304.0f);
111 for (t = 0;t < tmax;t++, i -= 16)
114 // make sure some part of it is visible on this line
117 maxdist2 = maxdist - td;
118 for (s = 0;s < smax;s++)
120 if (sdtable[s] < maxdist2)
122 k = dlightdivtable[(sdtable[s] + td) >> 7] - subtract;
126 bl[1] += (green * k);
141 static int R_FloatAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surface)
143 int lnum, s, t, smax, tmax, smax3, lit, impacts, impactt;
144 float sdtable[256], *bl, k, dist, dist2, maxdist, maxdist2, maxdist3, td1, td, red, green, blue, impact[3], local[3], subtract, planenormal[3], planedist;
149 smax = (surface->extents[0] >> 4) + 1;
150 tmax = (surface->extents[1] >> 4) + 1;
153 for (lnum = 0, light = r_dlight;lnum < r_numdlights;lnum++, light++)
155 if (!(surface->dlightbits[lnum >> 5] & (1 << (lnum & 31))))
156 continue; // not lit by this light
158 Matrix4x4_Transform(matrix, light->origin, local);
159 VectorCopy(surface->mesh.data_normal3f, planenormal);
160 planedist = DotProduct(surface->mesh.data_vertex3f, planenormal);
161 dist = DotProduct(local, planenormal) - planedist;
163 // for comparisons to minimum acceptable light
164 // compensate for LIGHTOFFSET
165 maxdist = (int) light->rtlight.lightmap_cullradius2 + LIGHTOFFSET;
168 dist2 += LIGHTOFFSET;
169 if (dist2 >= maxdist)
172 VectorMA(local, -dist, planenormal, impact);
174 impacts = DotProduct (impact, surface->texinfo->vecs[0]) + surface->texinfo->vecs[0][3] - surface->texturemins[0];
175 impactt = DotProduct (impact, surface->texinfo->vecs[1]) + surface->texinfo->vecs[1][3] - surface->texturemins[1];
177 td = bound(0, impacts, smax * 16) - impacts;
178 td1 = bound(0, impactt, tmax * 16) - impactt;
179 td = td * td + td1 * td1 + dist2;
183 // reduce calculations
184 for (s = 0, td1 = impacts; s < smax; s++, td1 -= 16.0f)
185 sdtable[s] = td1 * td1 + dist2;
187 maxdist3 = maxdist - dist2;
189 // convert to 8.8 blocklights format
190 red = light->rtlight.lightmap_light[0];
191 green = light->rtlight.lightmap_light[1];
192 blue = light->rtlight.lightmap_light[2];
193 subtract = light->rtlight.lightmap_subtract * 32768.0f;
194 bl = floatblocklights;
197 for (t = 0;t < tmax;t++, td1 -= 16.0f)
200 // make sure some part of it is visible on this line
203 maxdist2 = maxdist - td;
204 for (s = 0;s < smax;s++)
206 if (sdtable[s] < maxdist2)
208 k = (32768.0f / (sdtable[s] + td)) - subtract;
228 Combine and scale multiple lightmaps into the 8.8 format in blocklights
231 static void R_BuildLightMap (const entity_render_t *ent, msurface_t *surface)
233 if (!r_floatbuildlightmap.integer)
235 int smax, tmax, i, j, size, size3, maps, stride, l;
236 unsigned int *bl, scale;
237 qbyte *lightmap, *out, *stain;
239 // update cached lighting info
240 surface->cached_dlight = 0;
242 smax = (surface->extents[0]>>4)+1;
243 tmax = (surface->extents[1]>>4)+1;
246 lightmap = surface->samples;
248 // set to full bright if no light data
250 if (!ent->model->brushq1.lightdata)
252 for (i = 0;i < size3;i++)
258 memset(bl, 0, size*3*sizeof(unsigned int));
260 if (surface->dlightframe == r_framecount)
262 surface->cached_dlight = R_IntAddDynamicLights(&ent->inversematrix, surface);
263 if (surface->cached_dlight)
267 // add all the lightmaps
271 for (maps = 0;maps < MAXLIGHTMAPS && surface->styles[maps] != 255;maps++, lightmap += size3)
272 for (scale = d_lightstylevalue[surface->styles[maps]], i = 0;i < size3;i++)
273 bl[i] += lightmap[i] * scale;
277 stain = surface->stainsamples;
280 // the >> 16 shift adjusts down 8 bits to account for the stainmap
281 // scaling, and remaps the 0-65536 (2x overbright) to 0-256, it will
282 // be doubled during rendering to achieve 2x overbright
283 // (0 = 0.0, 128 = 1.0, 256 = 2.0)
284 if (ent->model->brushq1.lightmaprgba)
286 stride = (surface->lightmaptexturestride - smax) * 4;
287 for (i = 0;i < tmax;i++, out += stride)
289 for (j = 0;j < smax;j++)
291 l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
292 l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
293 l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
300 stride = (surface->lightmaptexturestride - smax) * 3;
301 for (i = 0;i < tmax;i++, out += stride)
303 for (j = 0;j < smax;j++)
305 l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
306 l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
307 l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
312 R_UpdateTexture(surface->lightmaptexture, templight);
316 int smax, tmax, i, j, size, size3, maps, stride, l;
318 qbyte *lightmap, *out, *stain;
320 // update cached lighting info
321 surface->cached_dlight = 0;
323 smax = (surface->extents[0]>>4)+1;
324 tmax = (surface->extents[1]>>4)+1;
327 lightmap = surface->samples;
329 // set to full bright if no light data
330 bl = floatblocklights;
331 if (!ent->model->brushq1.lightdata)
333 for (i = 0;i < size3;i++)
338 memset(bl, 0, size*3*sizeof(float));
340 if (surface->dlightframe == r_framecount)
342 surface->cached_dlight = R_FloatAddDynamicLights(&ent->inversematrix, surface);
343 if (surface->cached_dlight)
347 // add all the lightmaps
350 bl = floatblocklights;
351 for (maps = 0;maps < MAXLIGHTMAPS && surface->styles[maps] != 255;maps++, lightmap += size3)
352 for (scale = d_lightstylevalue[surface->styles[maps]], i = 0;i < size3;i++)
353 bl[i] += lightmap[i] * scale;
357 stain = surface->stainsamples;
358 bl = floatblocklights;
360 // this scaling adjusts down 8 bits to account for the stainmap
361 // scaling, and remaps the 0.0-2.0 (2x overbright) to 0-256, it will
362 // be doubled during rendering to achieve 2x overbright
363 // (0 = 0.0, 128 = 1.0, 256 = 2.0)
364 scale = 1.0f / (1 << 16);
365 if (ent->model->brushq1.lightmaprgba)
367 stride = (surface->lightmaptexturestride - smax) * 4;
368 for (i = 0;i < tmax;i++, out += stride)
370 for (j = 0;j < smax;j++)
372 l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
373 l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
374 l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
381 stride = (surface->lightmaptexturestride - smax) * 3;
382 for (i = 0;i < tmax;i++, out += stride)
384 for (j = 0;j < smax;j++)
386 l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
387 l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
388 l = *bl++ * *stain++ * scale;*out++ = min(l, 255);
393 R_UpdateTexture(surface->lightmaptexture, templight);
397 void R_StainNode (mnode_t *node, model_t *model, const vec3_t origin, float radius, const float fcolor[8])
399 float ndist, a, ratio, maxdist, maxdist2, maxdist3, invradius, sdtable[256], td, dist2;
400 msurface_t *surface, *endsurface;
401 int i, s, t, smax, tmax, smax3, impacts, impactt, stained;
405 maxdist = radius * radius;
406 invradius = 1.0f / radius;
411 ndist = PlaneDiff(origin, node->plane);
414 node = node->children[0];
419 node = node->children[1];
423 dist2 = ndist * ndist;
424 maxdist3 = maxdist - dist2;
426 if (node->plane->type < 3)
428 VectorCopy(origin, impact);
429 impact[node->plane->type] -= ndist;
433 impact[0] = origin[0] - node->plane->normal[0] * ndist;
434 impact[1] = origin[1] - node->plane->normal[1] * ndist;
435 impact[2] = origin[2] - node->plane->normal[2] * ndist;
438 for (surface = model->brush.data_surfaces + node->firstsurface, endsurface = surface + node->numsurfaces;surface < endsurface;surface++)
440 if (surface->stainsamples)
442 smax = (surface->extents[0] >> 4) + 1;
443 tmax = (surface->extents[1] >> 4) + 1;
445 impacts = DotProduct (impact, surface->texinfo->vecs[0]) + surface->texinfo->vecs[0][3] - surface->texturemins[0];
446 impactt = DotProduct (impact, surface->texinfo->vecs[1]) + surface->texinfo->vecs[1][3] - surface->texturemins[1];
448 s = bound(0, impacts, smax * 16) - impacts;
449 t = bound(0, impactt, tmax * 16) - impactt;
450 i = s * s + t * t + dist2;
454 // reduce calculations
455 for (s = 0, i = impacts; s < smax; s++, i -= 16)
456 sdtable[s] = i * i + dist2;
458 bl = surface->stainsamples;
463 for (t = 0;t < tmax;t++, i -= 16)
466 // make sure some part of it is visible on this line
469 maxdist2 = maxdist - td;
470 for (s = 0;s < smax;s++)
472 if (sdtable[s] < maxdist2)
474 ratio = lhrandom(0.0f, 1.0f);
475 a = (fcolor[3] + ratio * fcolor[7]) * (1.0f - sqrt(sdtable[s] + td) * invradius);
476 if (a >= (1.0f / 64.0f))
480 bl[0] = (qbyte) ((float) bl[0] + a * ((fcolor[0] + ratio * fcolor[4]) - (float) bl[0]));
481 bl[1] = (qbyte) ((float) bl[1] + a * ((fcolor[1] + ratio * fcolor[5]) - (float) bl[1]));
482 bl[2] = (qbyte) ((float) bl[2] + a * ((fcolor[2] + ratio * fcolor[6]) - (float) bl[2]));
492 // force lightmap upload
494 surface->cached_dlight = true;
498 if (node->children[0]->plane)
500 if (node->children[1]->plane)
502 R_StainNode(node->children[0], model, origin, radius, fcolor);
503 node = node->children[1];
508 node = node->children[0];
512 else if (node->children[1]->plane)
514 node = node->children[1];
519 void R_Stain (const vec3_t origin, float radius, int cr1, int cg1, int cb1, int ca1, int cr2, int cg2, int cb2, int ca2)
523 entity_render_t *ent;
526 if (r_refdef.worldmodel == NULL || !r_refdef.worldmodel->brush.data_nodes)
531 fcolor[3] = ca1 * (1.0f / 64.0f);
532 fcolor[4] = cr2 - cr1;
533 fcolor[5] = cg2 - cg1;
534 fcolor[6] = cb2 - cb1;
535 fcolor[7] = (ca2 - ca1) * (1.0f / 64.0f);
537 R_StainNode(r_refdef.worldmodel->brush.data_nodes + r_refdef.worldmodel->brushq1.hulls[0].firstclipnode, r_refdef.worldmodel, origin, radius, fcolor);
539 // look for embedded bmodels
540 for (n = 0;n < cl_num_brushmodel_entities;n++)
542 ent = cl_brushmodel_entities[n];
544 if (model && model->name[0] == '*')
546 Mod_CheckLoaded(model);
547 if (model->brush.data_nodes)
549 Matrix4x4_Transform(&ent->inversematrix, origin, org);
550 R_StainNode(model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode, model, org, radius, fcolor);
558 =============================================================
562 =============================================================
565 static void RSurf_AddLightmapToVertexColors_Color4f(const int *lightmapoffsets, float *c, int numverts, const qbyte *samples, int size3, const qbyte *styles)
570 if (styles[0] != 255)
572 for (i = 0;i < numverts;i++, c += 4)
574 lm = samples + lightmapoffsets[i];
575 scale = d_lightstylevalue[styles[0]] * (1.0f / 32768.0f);
576 VectorMA(c, scale, lm, c);
577 if (styles[1] != 255)
580 scale = d_lightstylevalue[styles[1]] * (1.0f / 32768.0f);
581 VectorMA(c, scale, lm, c);
582 if (styles[2] != 255)
585 scale = d_lightstylevalue[styles[2]] * (1.0f / 32768.0f);
586 VectorMA(c, scale, lm, c);
587 if (styles[3] != 255)
590 scale = d_lightstylevalue[styles[3]] * (1.0f / 32768.0f);
591 VectorMA(c, scale, lm, c);
599 static void RSurf_FogColors_Vertex3f_Color4f(const float *v, float *c, float colorscale, int numverts, const float *modelorg)
605 for (i = 0;i < numverts;i++, v += 3, c += 4)
607 VectorSubtract(v, modelorg, diff);
608 f = colorscale * (1 - exp(fogdensity/DotProduct(diff, diff)));
609 VectorScale(c, f, c);
612 else if (colorscale != 1)
613 for (i = 0;i < numverts;i++, c += 4)
614 VectorScale(c, colorscale, c);
617 static void RSurf_FoggedColors_Vertex3f_Color4f(const float *v, float *c, float r, float g, float b, float a, float colorscale, int numverts, const float *modelorg)
626 for (i = 0;i < numverts;i++, v += 3, c += 4)
628 VectorSubtract(v, modelorg, diff);
629 f = 1 - exp(fogdensity/DotProduct(diff, diff));
638 for (i = 0;i < numverts;i++, c += 4)
648 static void RSurf_FogPassColors_Vertex3f_Color4f(const float *v, float *c, float r, float g, float b, float a, float colorscale, int numverts, const float *modelorg)
655 for (i = 0;i < numverts;i++, v += 3, c += 4)
657 VectorSubtract(v, modelorg, diff);
658 f = exp(fogdensity/DotProduct(diff, diff));
666 static int RSurf_LightSeparate_Vertex3f_Color4f(const matrix4x4_t *matrix, const int *dlightbits, int numverts, const float *vert, float *color, float scale)
671 int i, l, lit = false;
672 const dlight_t *light;
674 for (l = 0;l < r_numdlights;l++)
676 if (dlightbits[l >> 5] & (1 << (l & 31)))
678 light = &r_dlight[l];
679 Matrix4x4_Transform(matrix, light->origin, lightorigin);
680 for (i = 0, v = vert, c = color;i < numverts;i++, v += 3, c += 4)
682 f = VectorDistance2(v, lightorigin) + LIGHTOFFSET;
683 if (f < light->rtlight.lightmap_cullradius2)
685 f = ((1.0f / f) - light->rtlight.lightmap_subtract) * scale;
686 VectorMA(c, f, light->rtlight.lightmap_light, c);
695 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
697 t->currentmaterialflags = t->basematerialflags;
698 t->currentalpha = ent->alpha;
699 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
700 t->currentalpha *= r_wateralpha.value;
701 if (ent->effects & EF_ADDITIVE)
702 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
703 if (t->currentalpha < 1 || t->skin.fog != NULL)
704 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
705 // we don't need to set currentframe if t->animated is false because
706 // it was already set up by the texture loader for non-animating
708 t->currentframe = t->anim_frames[ent->frame != 0][(t->anim_total[ent->frame != 0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[ent->frame != 0]) : 0];
711 void R_UpdateAllTextureInfo(entity_render_t *ent)
715 for (i = 0;i < ent->model->brush.num_textures;i++)
716 R_UpdateTextureInfo(ent, ent->model->brush.data_textures + i);
719 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
721 const entity_render_t *ent = calldata1;
722 const msurface_t *surface = ent->model->brush.data_surfaces + calldata2;
724 float base, colorscale;
727 float args[4] = {0.05f,0,0,0.04f};
728 int turb, fullbright;
730 texture = surface->texture;
731 R_UpdateTextureInfo(ent, texture);
732 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
733 return; // transparent sky is too difficult
735 R_Mesh_Matrix(&ent->matrix);
736 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
738 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
739 GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT));
740 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
741 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
742 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
743 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
745 GL_BlendFunc(GL_ONE, GL_ZERO);
747 turb = texture->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value;
748 fullbright = !(ent->flags & RENDER_LIGHT) || (texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !surface->samples;
749 base = fullbright ? 2.0f : r_ambient.value * (1.0f / 64.0f);
750 if (texture->currentmaterialflags & MATERIALFLAG_WATER)
752 if (texture->currentmaterialflags & MATERIALFLAG_WATER && gl_textureshader && r_watershader.value && !fogenabled && fullbright && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1)
754 // NVIDIA Geforce3 distortion texture shader on water
755 GL_Color(1, 1, 1, texture->currentalpha);
756 memset(&m, 0, sizeof(m));
757 m.pointer_vertex = surface->mesh.data_vertex3f;
758 m.tex[0] = R_GetTexture(mod_shared_distorttexture[(int)(r_refdef.time * 16)&63]);
759 m.tex[1] = R_GetTexture(texture->skin.base);
760 m.texcombinergb[0] = GL_REPLACE;
761 m.texcombinergb[1] = GL_REPLACE;
762 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
763 m.pointer_texcoord[1] = surface->mesh.data_texcoordtexture2f;
764 Matrix4x4_CreateFromQuakeEntity(&m.texmatrix[0], 0, 0, 0, 0, 0, 0, r_watershader.value);
765 Matrix4x4_CreateTranslate(&m.texmatrix[1], sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
769 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
771 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV);
772 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB);
773 qglTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, &args[0]);
774 qglEnable(GL_TEXTURE_SHADER_NV);
776 GL_LockArrays(0, surface->mesh.num_vertices);
777 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
780 qglDisable(GL_TEXTURE_SHADER_NV);
781 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
786 memset(&m, 0, sizeof(m));
787 m.pointer_vertex = surface->mesh.data_vertex3f;
788 m.pointer_color = varray_color4f;
789 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
790 m.tex[0] = R_GetTexture(texture->skin.base);
793 // scrolling in texture matrix
794 Matrix4x4_CreateTranslate(&m.texmatrix[0], sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
797 if (gl_combine.integer)
799 m.texrgbscale[0] = 4;
802 R_FillColors(varray_color4f, surface->mesh.num_vertices, base * ent->colormod[0], base * ent->colormod[1], base * ent->colormod[2], texture->currentalpha);
805 if (surface->dlightframe == r_framecount)
806 RSurf_LightSeparate_Vertex3f_Color4f(&ent->inversematrix, surface->dlightbits, surface->mesh.num_vertices, surface->mesh.data_vertex3f, varray_color4f, 1);
807 if (surface->samples)
808 RSurf_AddLightmapToVertexColors_Color4f(surface->mesh.data_lightmapoffsets, varray_color4f,surface->mesh.num_vertices, surface->samples, ((surface->extents[0]>>4)+1)*((surface->extents[1]>>4)+1)*3, surface->styles);
810 RSurf_FogColors_Vertex3f_Color4f(surface->mesh.data_vertex3f, varray_color4f, colorscale, surface->mesh.num_vertices, modelorg);
812 GL_LockArrays(0, surface->mesh.num_vertices);
813 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
815 if (texture->skin.glow)
817 memset(&m, 0, sizeof(m));
818 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
820 m.pointer_color = varray_color4f;
821 m.tex[0] = R_GetTexture(texture->skin.glow);
822 m.pointer_vertex = surface->mesh.data_vertex3f;
825 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
828 // scrolling in texture matrix
829 Matrix4x4_CreateTranslate(&m.texmatrix[0], sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
833 RSurf_FoggedColors_Vertex3f_Color4f(surface->mesh.data_vertex3f, varray_color4f, 1, 1, 1, texture->currentalpha, 1, surface->mesh.num_vertices, modelorg);
834 GL_LockArrays(0, surface->mesh.num_vertices);
835 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
838 if (fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD))
840 memset(&m, 0, sizeof(m));
841 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
843 m.pointer_color = varray_color4f;
844 m.tex[0] = R_GetTexture(texture->skin.fog);
845 m.pointer_vertex = surface->mesh.data_vertex3f;
848 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
851 // scrolling in texture matrix
852 Matrix4x4_CreateTranslate(&m.texmatrix[0], sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
856 RSurf_FogPassColors_Vertex3f_Color4f(surface->mesh.data_vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], texture->currentalpha, 1, surface->mesh.num_vertices, modelorg);
857 GL_LockArrays(0, surface->mesh.num_vertices);
858 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
864 void R_DrawSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, msurface_t **texturesurfacelist)
866 int texturesurfaceindex;
867 vec3_t tempcenter, center, modelorg;
876 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
877 c_faces += texturenumsurfaces;
878 // gl_lightmaps debugging mode skips normal texturing
879 if (gl_lightmaps.integer)
881 GL_BlendFunc(GL_ONE, GL_ZERO);
884 qglDisable(GL_CULL_FACE);
885 GL_Color(1, 1, 1, 1);
886 memset(&m, 0, sizeof(m));
887 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
889 surface = texturesurfacelist[texturesurfaceindex];
890 m.tex[0] = R_GetTexture(surface->lightmaptexture);
891 m.pointer_texcoord[0] = surface->mesh.data_texcoordlightmap2f;
892 if (surface->lightmaptexture)
894 GL_Color(1, 1, 1, 1);
895 m.pointer_color = NULL;
898 m.pointer_color = surface->mesh.data_lightmapcolor4f;
899 m.pointer_vertex = surface->mesh.data_vertex3f;
901 GL_LockArrays(0, surface->mesh.num_vertices);
902 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
905 qglEnable(GL_CULL_FACE);
908 // transparent surfaces get sorted for later drawing
909 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
911 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
913 surface = texturesurfacelist[texturesurfaceindex];
914 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
915 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
916 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
917 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
918 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->brush.data_surfaces);
922 if (texture->currentmaterialflags & MATERIALFLAG_WALL)
924 dolightmap = (ent->flags & RENDER_LIGHT);
926 doambient = r_ambient.value > 0;
927 dodetail = texture->skin.detail != NULL && r_detailtextures.integer != 0;
928 doglow = texture->skin.glow != NULL;
930 // multitexture cases
931 if (r_textureunits.integer >= 2 && gl_combine.integer && dobase && dolightmap)
933 GL_BlendFunc(GL_ONE, GL_ZERO);
936 GL_Color(1, 1, 1, 1);
937 GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
938 memset(&m, 0, sizeof(m));
939 m.tex[0] = R_GetTexture(texture->skin.base);
941 m.texrgbscale[1] = 2;
943 if (r_textureunits.integer >= 4 && !doambient && dodetail && doglow)
945 m.tex[2] = R_GetTexture(texture->skin.detail);
946 m.texrgbscale[2] = 2;
948 m.tex[3] = R_GetTexture(texture->skin.glow);
949 m.texcombinergb[3] = GL_ADD;
951 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
953 surface = texturesurfacelist[texturesurfaceindex];
954 m.tex[1] = R_GetTexture(surface->lightmaptexture);
955 m.pointer_vertex = surface->mesh.data_vertex3f;
956 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
957 m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
958 m.pointer_texcoord[2] = surface->mesh.data_texcoorddetail2f;
959 m.pointer_texcoord[3] = surface->mesh.data_texcoordtexture2f;
961 GL_LockArrays(0, surface->mesh.num_vertices);
962 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
966 else if (r_textureunits.integer >= 3 && !doambient && dodetail)
968 m.tex[2] = R_GetTexture(texture->skin.detail);
969 m.texrgbscale[2] = 2;
971 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
973 surface = texturesurfacelist[texturesurfaceindex];
974 m.tex[1] = R_GetTexture(surface->lightmaptexture);
975 m.pointer_vertex = surface->mesh.data_vertex3f;
976 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
977 m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
978 m.pointer_texcoord[2] = surface->mesh.data_texcoorddetail2f;
980 GL_LockArrays(0, surface->mesh.num_vertices);
981 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
985 else if (r_textureunits.integer >= 3 && !doambient && !dodetail && doglow)
987 m.tex[2] = R_GetTexture(texture->skin.glow);
988 m.texcombinergb[2] = GL_ADD;
990 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
992 surface = texturesurfacelist[texturesurfaceindex];
993 m.tex[1] = R_GetTexture(surface->lightmaptexture);
994 m.pointer_vertex = surface->mesh.data_vertex3f;
995 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
996 m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
997 m.pointer_texcoord[2] = surface->mesh.data_texcoordtexture2f;
999 GL_LockArrays(0, surface->mesh.num_vertices);
1000 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1001 GL_LockArrays(0, 0);
1006 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1008 surface = texturesurfacelist[texturesurfaceindex];
1009 m.tex[1] = R_GetTexture(surface->lightmaptexture);
1010 m.pointer_vertex = surface->mesh.data_vertex3f;
1011 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
1012 m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
1014 GL_LockArrays(0, surface->mesh.num_vertices);
1015 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1016 GL_LockArrays(0, 0);
1020 // anything not handled above
1023 GL_BlendFunc(GL_ONE, GL_ZERO);
1026 GL_Color(1, 1, 1, 1);
1027 if (ent->flags & RENDER_LIGHT)
1028 GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
1030 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], 1);
1031 memset(&m, 0, sizeof(m));
1032 m.tex[0] = R_GetTexture(texture->skin.base);
1033 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1035 surface = texturesurfacelist[texturesurfaceindex];
1036 m.pointer_vertex = surface->mesh.data_vertex3f;
1037 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
1039 GL_LockArrays(0, surface->mesh.num_vertices);
1040 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1041 GL_LockArrays(0, 0);
1044 GL_DepthMask(false);
1047 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1048 GL_DepthMask(false);
1050 GL_Color(1, 1, 1, 1);
1051 memset(&m, 0, sizeof(m));
1052 m.tex[0] = R_GetTexture(texture->skin.base);
1053 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1055 surface = texturesurfacelist[texturesurfaceindex];
1056 m.tex[0] = R_GetTexture(surface->lightmaptexture);
1057 m.pointer_vertex = surface->mesh.data_vertex3f;
1058 m.pointer_texcoord[0] = surface->mesh.data_texcoordlightmap2f;
1060 GL_LockArrays(0, surface->mesh.num_vertices);
1061 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1062 GL_LockArrays(0, 0);
1067 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1068 GL_DepthMask(false);
1070 memset(&m, 0, sizeof(m));
1071 GL_Color(r_ambient.value * (1.0f / 128.0f) * ent->colormod[0], r_ambient.value * (1.0f / 128.0f) * ent->colormod[1], r_ambient.value * (1.0f / 128.0f) * ent->colormod[2], 1);
1072 m.tex[0] = R_GetTexture(texture->skin.base);
1073 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1075 surface = texturesurfacelist[texturesurfaceindex];
1076 m.pointer_vertex = surface->mesh.data_vertex3f;
1077 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
1079 GL_LockArrays(0, surface->mesh.num_vertices);
1080 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1081 GL_LockArrays(0, 0);
1086 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1087 GL_DepthMask(false);
1089 GL_Color(1, 1, 1, 1);
1090 memset(&m, 0, sizeof(m));
1091 m.tex[0] = R_GetTexture(texture->skin.detail);
1092 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1094 surface = texturesurfacelist[texturesurfaceindex];
1095 m.pointer_vertex = surface->mesh.data_vertex3f;
1096 m.pointer_texcoord[0] = surface->mesh.data_texcoorddetail2f;
1098 GL_LockArrays(0, surface->mesh.num_vertices);
1099 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1100 GL_LockArrays(0, 0);
1105 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1106 GL_DepthMask(false);
1108 GL_Color(1, 1, 1, 1);
1109 memset(&m, 0, sizeof(m));
1110 m.tex[0] = R_GetTexture(texture->skin.glow);
1111 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1113 surface = texturesurfacelist[texturesurfaceindex];
1114 m.pointer_vertex = surface->mesh.data_vertex3f;
1115 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
1117 GL_LockArrays(0, surface->mesh.num_vertices);
1118 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1119 GL_LockArrays(0, 0);
1124 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1125 GL_DepthMask(false);
1127 memset(&m, 0, sizeof(m));
1128 m.pointer_color = varray_color4f;
1129 m.tex[0] = R_GetTexture(texture->skin.glow);
1130 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1132 surface = texturesurfacelist[texturesurfaceindex];
1133 m.pointer_vertex = surface->mesh.data_vertex3f;
1135 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
1137 RSurf_FogPassColors_Vertex3f_Color4f(surface->mesh.data_vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], 1, 1, surface->mesh.num_vertices, modelorg);
1138 GL_LockArrays(0, surface->mesh.num_vertices);
1139 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1140 GL_LockArrays(0, 0);
1145 if (texture->currentmaterialflags & MATERIALFLAG_WATER)
1147 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1149 surface = texturesurfacelist[texturesurfaceindex];
1150 RSurfShader_Transparent_Callback(ent, surface - ent->model->brush.data_surfaces);
1154 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
1158 skyrendernow = false;
1159 if (skyrendermasked)
1162 // LordHavoc: HalfLife maps have freaky skypolys...
1163 if (!ent->model->brush.ishlbsp)
1165 R_Mesh_Matrix(&ent->matrix);
1166 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
1167 if (skyrendermasked)
1169 // depth-only (masking)
1170 GL_ColorMask(0,0,0,0);
1171 // just to make sure that braindead drivers don't draw anything
1172 // despite that colormask...
1173 GL_BlendFunc(GL_ZERO, GL_ONE);
1178 GL_BlendFunc(GL_ONE, GL_ZERO);
1182 memset(&m, 0, sizeof(m));
1183 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1185 surface = texturesurfacelist[texturesurfaceindex];
1186 m.pointer_vertex = surface->mesh.data_vertex3f;
1188 GL_LockArrays(0, surface->mesh.num_vertices);
1189 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1190 GL_LockArrays(0, 0);
1192 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1198 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
1200 int i, j, f, flagsmask;
1201 msurface_t *surface, **surfacechain;
1202 texture_t *t, *texture;
1203 model_t *model = ent->model;
1205 const int maxsurfacelist = 1024;
1206 int numsurfacelist = 0;
1207 msurface_t *surfacelist[1024];
1210 R_Mesh_Matrix(&ent->matrix);
1211 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
1213 if (ent != r_refdef.worldentity)
1215 // because bmodels can be reused, we have to clear dlightframe every time
1216 surface = model->brush.data_surfaces + model->firstmodelsurface;
1217 for (i = 0;i < model->nummodelsurfaces;i++, surface++)
1218 surface->dlightframe = -1;
1221 // update light styles
1224 if (r_dynamic.integer && !r_rtdlight)
1226 for (i = 0;i < model->brushq1.light_styles;i++)
1228 if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
1230 model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
1231 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
1232 for (;(surface = *surfacechain);surfacechain++)
1233 surface->cached_dlight = true;
1238 R_UpdateAllTextureInfo(ent);
1239 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
1243 for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
1245 if (ent != r_refdef.worldentity || r_worldsurfacevisible[j])
1247 surface = model->brush.data_surfaces + j;
1248 if (t != surface->texture)
1252 R_DrawSurfaceList(ent, texture, numsurfacelist, surfacelist);
1255 t = surface->texture;
1256 f = t->currentmaterialflags & flagsmask;
1257 texture = t->currentframe;
1261 // add face to draw list and update lightmap if necessary
1262 if (surface->cached_dlight && surface->lightmaptexture != NULL)
1263 R_BuildLightMap(ent, surface);
1264 surfacelist[numsurfacelist++] = surface;
1265 if (numsurfacelist >= maxsurfacelist)
1267 R_DrawSurfaceList(ent, texture, numsurfacelist, surfacelist);
1274 R_DrawSurfaceList(ent, texture, numsurfacelist, surfacelist);
1277 static void R_DrawPortal_Callback(const void *calldata1, int calldata2)
1282 const mportal_t *portal = calldata1;
1283 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1284 GL_DepthMask(false);
1286 R_Mesh_Matrix(&r_identitymatrix);
1288 memset(&m, 0, sizeof(m));
1289 m.pointer_vertex = varray_vertex3f;
1293 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f),
1294 ((i & 0x0038) >> 3) * (1.0f / 7.0f),
1295 ((i & 0x01C0) >> 6) * (1.0f / 7.0f),
1297 if (PlaneDiff(r_vieworigin, (&portal->plane)) < 0)
1299 for (i = portal->numpoints - 1, v = varray_vertex3f;i >= 0;i--, v += 3)
1300 VectorCopy(portal->points[i].position, v);
1303 for (i = 0, v = varray_vertex3f;i < portal->numpoints;i++, v += 3)
1304 VectorCopy(portal->points[i].position, v);
1305 GL_LockArrays(0, portal->numpoints);
1306 R_Mesh_Draw(portal->numpoints, portal->numpoints - 2, polygonelements);
1307 GL_LockArrays(0, 0);
1310 // LordHavoc: this is just a nice debugging tool, very slow
1311 static void R_DrawPortals(void)
1316 model_t *model = r_refdef.worldmodel;
1319 for (portalnum = 0, portal = model->brush.data_portals;portalnum < model->brush.num_portals;portalnum++, portal++)
1321 if (portal->numpoints <= POLYGONELEMENTS_MAXPOINTS)
1322 if (!R_CullBox(portal->mins, portal->maxs))
1324 VectorClear(center);
1325 for (i = 0;i < portal->numpoints;i++)
1326 VectorAdd(center, portal->points[i].position, center);
1327 f = ixtable[portal->numpoints];
1328 VectorScale(center, f, center);
1329 R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, portal, portalnum);
1334 void R_WorldVisibility(void)
1339 model_t *model = r_refdef.worldmodel;
1344 // if possible find the leaf the view origin is in
1345 viewleaf = model->brushq1.PointInLeaf ? model->brushq1.PointInLeaf(model, r_vieworigin) : NULL;
1346 // if possible fetch the visible cluster bits
1347 if (model->brush.FatPVS)
1348 model->brush.FatPVS(model, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
1350 // clear the visible surface and leaf flags arrays
1351 memset(r_worldsurfacevisible, 0, model->brush.num_surfaces);
1352 memset(r_worldleafvisible, 0, model->brush.num_leafs);
1354 // if the user prefers surfaceworldnode (testing?) or the viewleaf could
1355 // not be found, or the viewleaf is not part of the visible world
1356 // (floating around in the void), use the pvs method
1357 if (r_surfaceworldnode.integer || !viewleaf || viewleaf->clusterindex < 0)
1360 // similar to quake's RecursiveWorldNode but without cache misses
1361 for (j = 0, leaf = model->brush.data_leafs;j < model->brush.num_leafs;j++, leaf++)
1363 // if leaf is in current pvs and on the screen, mark its surfaces
1364 if (CHECKPVSBIT(r_pvsbits, leaf->clusterindex) && !R_CullBox(leaf->mins, leaf->maxs))
1367 r_worldleafvisible[j] = true;
1368 if (leaf->numleafsurfaces)
1369 for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
1370 r_worldsurfacevisible[*mark] = true;
1378 mleaf_t *leafstack[8192];
1380 // follows portals leading outward from viewleaf, does not venture
1381 // offscreen or into leafs that are not visible, faster than Quake's
1382 // RecursiveWorldNode and vastly better in unvised maps, often culls a
1383 // lot of surface that pvs alone would miss
1384 leafstack[0] = viewleaf;
1386 while (leafstackpos)
1389 leaf = leafstack[--leafstackpos];
1390 r_worldleafvisible[leaf - model->brush.data_leafs] = true;
1391 // mark any surfaces bounding this leaf
1392 if (leaf->numleafsurfaces)
1393 for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
1394 r_worldsurfacevisible[*mark] = true;
1395 // follow portals into other leafs
1397 // if viewer is behind portal (portal faces outward into the scene)
1398 // and the portal polygon's bounding box is on the screen
1399 // and the leaf has not been visited yet
1400 // and the leaf is visible in the pvs
1401 // (the first two checks won't cause as many cache misses as the leaf checks)
1402 for (p = leaf->portals;p;p = p->next)
1403 if (DotProduct(r_vieworigin, p->plane.normal) < (p->plane.dist + 1) && !R_CullBox(p->mins, p->maxs) && !r_worldleafvisible[p->past - model->brush.data_leafs] && CHECKPVSBIT(r_pvsbits, p->past->clusterindex))
1404 leafstack[leafstackpos++] = p->past;
1408 if (r_drawportals.integer)
1412 void R_Q1BSP_DrawSky(entity_render_t *ent)
1414 if (ent->model == NULL)
1416 if (r_drawcollisionbrushes.integer < 2)
1417 R_DrawSurfaces(ent, true);
1420 void R_Q1BSP_Draw(entity_render_t *ent)
1422 if (ent->model == NULL)
1425 if (r_drawcollisionbrushes.integer < 2)
1426 R_DrawSurfaces(ent, false);
1429 void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outclusterlist, qbyte *outclusterpvs, int *outnumclusterspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer)
1431 model_t *model = ent->model;
1432 vec3_t lightmins, lightmaxs;
1433 int t, leafindex, leafsurfaceindex, surfaceindex, triangleindex, outnumclusters = 0, outnumsurfaces = 0;
1436 msurface_t *surface;
1439 lightmins[0] = relativelightorigin[0] - lightradius;
1440 lightmins[1] = relativelightorigin[1] - lightradius;
1441 lightmins[2] = relativelightorigin[2] - lightradius;
1442 lightmaxs[0] = relativelightorigin[0] + lightradius;
1443 lightmaxs[1] = relativelightorigin[1] + lightradius;
1444 lightmaxs[2] = relativelightorigin[2] + lightradius;
1445 *outnumclusterspointer = 0;
1446 *outnumsurfacespointer = 0;
1447 memset(outclusterpvs, 0, model->brush.num_pvsclusterbytes);
1448 memset(outsurfacepvs, 0, (model->nummodelsurfaces + 7) >> 3);
1451 VectorCopy(lightmins, outmins);
1452 VectorCopy(lightmaxs, outmaxs);
1455 VectorCopy(relativelightorigin, outmins);
1456 VectorCopy(relativelightorigin, outmaxs);
1457 if (model->brush.GetPVS)
1458 pvs = model->brush.GetPVS(model, relativelightorigin);
1461 R_UpdateAllTextureInfo(ent);
1462 // FIXME: use BSP recursion as lights are often small
1463 for (leafindex = 0, leaf = model->brush.data_leafs;leafindex < model->brush.num_leafs;leafindex++, leaf++)
1465 if (BoxesOverlap(lightmins, lightmaxs, leaf->mins, leaf->maxs) && (pvs == NULL || CHECKPVSBIT(pvs, leaf->clusterindex)))
1467 outmins[0] = min(outmins[0], leaf->mins[0]);
1468 outmins[1] = min(outmins[1], leaf->mins[1]);
1469 outmins[2] = min(outmins[2], leaf->mins[2]);
1470 outmaxs[0] = max(outmaxs[0], leaf->maxs[0]);
1471 outmaxs[1] = max(outmaxs[1], leaf->maxs[1]);
1472 outmaxs[2] = max(outmaxs[2], leaf->maxs[2]);
1475 if (!CHECKPVSBIT(outclusterpvs, leaf->clusterindex))
1477 SETPVSBIT(outclusterpvs, leaf->clusterindex);
1478 outclusterlist[outnumclusters++] = leaf->clusterindex;
1483 for (leafsurfaceindex = 0;leafsurfaceindex < leaf->numleafsurfaces;leafsurfaceindex++)
1485 surfaceindex = leaf->firstleafsurface[leafsurfaceindex];
1486 if (!CHECKPVSBIT(outsurfacepvs, surfaceindex))
1488 surface = model->brush.data_surfaces + surfaceindex;
1489 if (BoxesOverlap(lightmins, lightmaxs, surface->mins, surface->maxs) && ((surface->texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL) && !surface->texture->skin.fog)
1491 for (triangleindex = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;triangleindex < surface->mesh.num_triangles;triangleindex++, t++, e += 3)
1493 v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3;
1494 v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3;
1495 v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3;
1496 if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
1498 SETPVSBIT(outsurfacepvs, surfaceindex);
1499 outsurfacelist[outnumsurfaces++] = surfaceindex;
1510 // limit combined leaf box to light boundaries
1511 outmins[0] = max(outmins[0], lightmins[0]);
1512 outmins[1] = max(outmins[1], lightmins[1]);
1513 outmins[2] = max(outmins[2], lightmins[2]);
1514 outmaxs[0] = min(outmaxs[0], lightmaxs[0]);
1515 outmaxs[1] = min(outmaxs[1], lightmaxs[1]);
1516 outmaxs[2] = min(outmaxs[2], lightmaxs[2]);
1518 *outnumclusterspointer = outnumclusters;
1519 *outnumsurfacespointer = outnumsurfaces;
1522 void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist, const vec3_t lightmins, const vec3_t lightmaxs)
1524 model_t *model = ent->model;
1525 msurface_t *surface;
1526 int surfacelistindex;
1527 if (r_drawcollisionbrushes.integer < 2)
1529 R_Mesh_Matrix(&ent->matrix);
1530 R_Shadow_PrepareShadowMark(model->brush.shadowmesh->numtriangles);
1531 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
1533 surface = model->brush.data_surfaces + surfacelist[surfacelistindex];
1534 R_Shadow_MarkVolumeFromBox(surface->num_firstshadowmeshtriangle, surface->mesh.num_triangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, relativelightorigin, lightmins, lightmaxs, surface->mins, surface->maxs);
1536 R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, lightradius + model->radius + r_shadow_projectdistance.value, numshadowmark, shadowmarklist);
1540 void R_Q1BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int numsurfaces, const int *surfacelist)
1542 model_t *model = ent->model;
1543 msurface_t *surface;
1545 int surfacelistindex;
1546 if (r_drawcollisionbrushes.integer < 2)
1548 R_Mesh_Matrix(&ent->matrix);
1549 if (!r_shadow_compilingrtlight)
1550 R_UpdateAllTextureInfo(ent);
1551 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
1553 surface = model->brush.data_surfaces + surfacelist[surfacelistindex];
1554 if (r_shadow_compilingrtlight)
1556 // if compiling an rtlight, capture the mesh
1557 t = surface->texture;
1558 if ((t->basematerialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL)
1559 Mod_ShadowMesh_AddMesh(r_shadow_mempool, r_shadow_compilingrtlight->static_meshchain_light, surface->texture->skin.base, surface->texture->skin.gloss, surface->texture->skin.nmap, surface->mesh.data_vertex3f, surface->mesh.data_svector3f, surface->mesh.data_tvector3f, surface->mesh.data_normal3f, surface->mesh.data_texcoordtexture2f, surface->mesh.num_triangles, surface->mesh.data_element3i);
1561 else if (ent != r_refdef.worldentity || r_worldsurfacevisible[surfacelist[surfacelistindex]])
1563 t = surface->texture->currentframe;
1564 // FIXME: transparent surfaces need to be lit later
1565 if ((t->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL)
1566 R_Shadow_RenderLighting(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i, surface->mesh.data_vertex3f, surface->mesh.data_svector3f, surface->mesh.data_tvector3f, surface->mesh.data_normal3f, surface->mesh.data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, t->skin.base, t->skin.nmap, t->skin.gloss, lightcubemap, ambientscale, diffusescale, specularscale);
1572 void R_DrawCollisionBrush(colbrushf_t *brush)
1576 memset(&m, 0, sizeof(m));
1577 m.pointer_vertex = brush->points->v;
1579 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
1580 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
1581 GL_LockArrays(0, brush->numpoints);
1582 R_Mesh_Draw(brush->numpoints, brush->numtriangles, brush->elements);
1583 GL_LockArrays(0, 0);
1586 void R_Q3BSP_DrawCollisionSurface(entity_render_t *ent, msurface_t *surface)
1590 if (!surface->mesh.num_collisiontriangles)
1592 memset(&m, 0, sizeof(m));
1593 m.pointer_vertex = surface->mesh.data_collisionvertex3f;
1595 i = (int)(((size_t)surface) / sizeof(msurface_t));
1596 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
1597 GL_LockArrays(0, surface->mesh.num_collisionvertices);
1598 R_Mesh_Draw(surface->mesh.num_collisionvertices, surface->mesh.num_collisiontriangles, surface->mesh.data_collisionelement3i);
1599 GL_LockArrays(0, 0);
1602 void R_Q3BSP_DrawFace_TransparentCallback(const void *voident, int surfacenumber)
1604 const entity_render_t *ent = voident;
1605 msurface_t *surface = ent->model->brush.data_surfaces + surfacenumber;
1607 R_Mesh_Matrix(&ent->matrix);
1608 memset(&m, 0, sizeof(m));
1609 if ((ent->effects & EF_ADDITIVE) || (surface->texture->textureflags & Q3TEXTUREFLAG_ADDITIVE))
1610 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1612 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1613 GL_DepthMask(false);
1614 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1615 m.tex[0] = R_GetTexture(surface->texture->skin.base);
1616 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
1617 // LordHavoc: quake3 was not able to do this; lit transparent surfaces
1618 if (gl_combine.integer)
1620 m.texrgbscale[0] = 2;
1621 if (r_textureunits.integer >= 2)
1623 m.tex[1] = R_GetTexture(surface->lightmaptexture);
1624 m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
1625 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
1629 if (ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1 && ent->alpha == 1)
1630 m.pointer_color = surface->mesh.data_lightmapcolor4f;
1634 for (i = 0;i < surface->mesh.num_vertices;i++)
1636 varray_color4f[i*4+0] = surface->mesh.data_lightmapcolor4f[i*4+0] * ent->colormod[0];
1637 varray_color4f[i*4+1] = surface->mesh.data_lightmapcolor4f[i*4+1] * ent->colormod[1];
1638 varray_color4f[i*4+2] = surface->mesh.data_lightmapcolor4f[i*4+2] * ent->colormod[2];
1639 varray_color4f[i*4+3] = surface->mesh.data_lightmapcolor4f[i*4+3] * ent->alpha;
1641 m.pointer_color = varray_color4f;
1648 for (i = 0;i < surface->mesh.num_vertices;i++)
1650 varray_color4f[i*4+0] = surface->mesh.data_lightmapcolor4f[i*4+0] * ent->colormod[0] * 2.0f;
1651 varray_color4f[i*4+1] = surface->mesh.data_lightmapcolor4f[i*4+1] * ent->colormod[1] * 2.0f;
1652 varray_color4f[i*4+2] = surface->mesh.data_lightmapcolor4f[i*4+2] * ent->colormod[2] * 2.0f;
1653 varray_color4f[i*4+3] = surface->mesh.data_lightmapcolor4f[i*4+3] * ent->alpha;
1655 m.pointer_color = varray_color4f;
1657 if (surface->texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
1660 float center[3], center2[3], forward[3], right[3], up[3], v[4][3];
1661 matrix4x4_t matrix1, imatrix1;
1662 R_Mesh_Matrix(&r_identitymatrix);
1663 // a single autosprite surface can contain multiple sprites...
1664 for (j = 0;j < surface->mesh.num_vertices - 3;j += 4)
1666 VectorClear(center);
1667 for (i = 0;i < 4;i++)
1668 VectorAdd(center, surface->mesh.data_vertex3f + (j+i) * 3, center);
1669 VectorScale(center, 0.25f, center);
1670 Matrix4x4_Transform(&ent->matrix, center, center2);
1671 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1672 Matrix4x4_FromVectors(&matrix1, surface->mesh.data_normal3f + j*3, surface->mesh.data_svector3f + j*3, surface->mesh.data_tvector3f + j*3, center);
1673 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1674 for (i = 0;i < 4;i++)
1675 Matrix4x4_Transform(&imatrix1, surface->mesh.data_vertex3f + (j+i)*3, v[i]);
1676 if (surface->texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1678 forward[0] = r_vieworigin[0] - center2[0];
1679 forward[1] = r_vieworigin[1] - center2[1];
1681 VectorNormalize(forward);
1682 right[0] = forward[1];
1683 right[1] = -forward[0];
1691 VectorCopy(r_viewforward, forward);
1692 VectorCopy(r_viewright, right);
1693 VectorCopy(r_viewup, up);
1695 for (i = 0;i < 4;i++)
1696 VectorMAMAMAM(1, center2, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (i+j) * 3);
1698 m.pointer_vertex = varray_vertex3f;
1701 m.pointer_vertex = surface->mesh.data_vertex3f;
1703 if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1704 qglDisable(GL_CULL_FACE);
1705 GL_LockArrays(0, surface->mesh.num_vertices);
1706 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1707 GL_LockArrays(0, 0);
1708 if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1709 qglEnable(GL_CULL_FACE);
1712 void R_Q3BSP_DrawFaceList(entity_render_t *ent, texture_t *t, int texturenumsurfaces, msurface_t **texturesurfacelist)
1714 int i, texturesurfaceindex;
1716 msurface_t *surface;
1717 qboolean dolightmap;
1724 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
1725 c_faces += texturenumsurfaces;
1726 // gl_lightmaps debugging mode skips normal texturing
1727 if (gl_lightmaps.integer)
1729 GL_BlendFunc(GL_ONE, GL_ZERO);
1732 qglDisable(GL_CULL_FACE);
1733 GL_Color(1, 1, 1, 1);
1734 memset(&m, 0, sizeof(m));
1735 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1737 surface = texturesurfacelist[texturesurfaceindex];
1738 m.tex[0] = R_GetTexture(surface->lightmaptexture);
1739 m.pointer_texcoord[0] = surface->mesh.data_texcoordlightmap2f;
1740 if (surface->lightmaptexture)
1742 GL_Color(1, 1, 1, 1);
1743 m.pointer_color = NULL;
1746 m.pointer_color = surface->mesh.data_lightmapcolor4f;
1747 m.pointer_vertex = surface->mesh.data_vertex3f;
1749 GL_LockArrays(0, surface->mesh.num_vertices);
1750 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1751 GL_LockArrays(0, 0);
1753 qglEnable(GL_CULL_FACE);
1756 // transparent surfaces get sorted for later drawing
1757 if ((t->surfaceparms & Q3SURFACEPARM_TRANS) || ent->alpha < 1 || (ent->effects & EF_ADDITIVE))
1759 vec3_t facecenter, center;
1760 // drawing sky transparently would be too difficult
1761 if (t->surfaceparms & Q3SURFACEPARM_SKY)
1763 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1765 surface = texturesurfacelist[texturesurfaceindex];
1766 facecenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
1767 facecenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
1768 facecenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
1769 Matrix4x4_Transform(&ent->matrix, facecenter, center);
1770 R_MeshQueue_AddTransparent(center, R_Q3BSP_DrawFace_TransparentCallback, ent, surface - ent->model->brush.data_surfaces);
1774 // sky surfaces draw sky if needed and render themselves as a depth mask
1775 if (t->surfaceparms & Q3SURFACEPARM_SKY)
1779 skyrendernow = false;
1780 if (skyrendermasked)
1783 if (!r_q3bsp_renderskydepth.integer)
1786 R_Mesh_Matrix(&ent->matrix);
1788 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
1789 if (skyrendermasked)
1791 // depth-only (masking)
1792 GL_ColorMask(0,0,0,0);
1793 // just to make sure that braindead drivers don't draw anything
1794 // despite that colormask...
1795 GL_BlendFunc(GL_ZERO, GL_ONE);
1800 GL_BlendFunc(GL_ONE, GL_ZERO);
1805 memset(&m, 0, sizeof(m));
1806 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1808 surface = texturesurfacelist[texturesurfaceindex];
1809 m.pointer_vertex = surface->mesh.data_vertex3f;
1811 GL_LockArrays(0, surface->mesh.num_vertices);
1812 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1813 GL_LockArrays(0, 0);
1815 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1818 // anything else is a typical wall, lightmap * texture + glow
1819 dolightmap = (ent->flags & RENDER_LIGHT);
1821 doambient = r_ambient.value > 0;
1822 dodetail = t->skin.detail != NULL && r_detailtextures.integer;
1823 doglow = t->skin.glow != NULL;
1825 if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1826 qglDisable(GL_CULL_FACE);
1827 if (!dolightmap && dobase)
1833 GL_BlendFunc(GL_ONE, GL_ZERO);
1834 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], 1);
1835 if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1836 qglDisable(GL_CULL_FACE);
1837 memset(&m, 0, sizeof(m));
1838 m.tex[0] = R_GetTexture(t->skin.base);
1839 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1841 surface = texturesurfacelist[texturesurfaceindex];
1842 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
1843 m.pointer_vertex = surface->mesh.data_vertex3f;
1845 GL_LockArrays(0, surface->mesh.num_vertices);
1846 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1847 GL_LockArrays(0, 0);
1850 if (r_lightmapintensity <= 0 && dolightmap && dobase)
1856 GL_BlendFunc(GL_ONE, GL_ZERO);
1857 GL_Color(0, 0, 0, 1);
1858 memset(&m, 0, sizeof(m));
1859 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1861 surface = texturesurfacelist[texturesurfaceindex];
1862 m.pointer_vertex = surface->mesh.data_vertex3f;
1864 GL_LockArrays(0, surface->mesh.num_vertices);
1865 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1866 GL_LockArrays(0, 0);
1869 if (r_textureunits.integer >= 2 && gl_combine.integer && dolightmap && dobase)
1871 // dualtexture combine
1876 GL_BlendFunc(GL_ONE, GL_ZERO);
1877 memset(&m, 0, sizeof(m));
1878 m.tex[0] = R_GetTexture(t->skin.base);
1879 GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
1880 m.pointer_color = NULL;
1881 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1883 surface = texturesurfacelist[texturesurfaceindex];
1884 if (!surface->lightmaptexture)
1886 m.tex[1] = R_GetTexture(surface->lightmaptexture);
1887 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
1888 m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
1889 m.texrgbscale[1] = 2;
1890 m.pointer_vertex = surface->mesh.data_vertex3f;
1892 GL_LockArrays(0, surface->mesh.num_vertices);
1893 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1894 GL_LockArrays(0, 0);
1896 if (r_lightmapintensity == 1 && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1)
1898 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1900 surface = texturesurfacelist[texturesurfaceindex];
1901 if (surface->lightmaptexture)
1903 m.tex[1] = R_GetTexture(surface->lightmaptexture);
1904 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
1905 m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
1906 m.texrgbscale[1] = 2;
1907 m.pointer_color = surface->mesh.data_lightmapcolor4f;
1908 m.pointer_vertex = surface->mesh.data_vertex3f;
1910 GL_LockArrays(0, surface->mesh.num_vertices);
1911 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1912 GL_LockArrays(0, 0);
1917 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1919 surface = texturesurfacelist[texturesurfaceindex];
1920 if (surface->lightmaptexture)
1922 m.tex[1] = R_GetTexture(surface->lightmaptexture);
1923 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
1924 m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
1925 m.texrgbscale[1] = 2;
1926 m.pointer_color = varray_color4f;
1927 for (i = 0;i < surface->mesh.num_vertices;i++)
1929 varray_color4f[i*4+0] = surface->mesh.data_lightmapcolor4f[i*4+0] * ent->colormod[0] * r_lightmapintensity;
1930 varray_color4f[i*4+1] = surface->mesh.data_lightmapcolor4f[i*4+1] * ent->colormod[1] * r_lightmapintensity;
1931 varray_color4f[i*4+2] = surface->mesh.data_lightmapcolor4f[i*4+2] * ent->colormod[2] * r_lightmapintensity;
1932 varray_color4f[i*4+3] = surface->mesh.data_lightmapcolor4f[i*4+3];
1934 m.pointer_vertex = surface->mesh.data_vertex3f;
1936 GL_LockArrays(0, surface->mesh.num_vertices);
1937 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1938 GL_LockArrays(0, 0);
1947 GL_BlendFunc(GL_ONE, GL_ZERO);
1948 memset(&m, 0, sizeof(m));
1949 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1951 surface = texturesurfacelist[texturesurfaceindex];
1952 m.tex[0] = R_GetTexture(surface->lightmaptexture);
1953 m.pointer_texcoord[0] = surface->mesh.data_texcoordlightmap2f;
1954 if (surface->lightmaptexture)
1955 m.pointer_color = NULL;
1957 m.pointer_color = surface->mesh.data_lightmapcolor4f;
1958 m.pointer_vertex = surface->mesh.data_vertex3f;
1960 GL_LockArrays(0, surface->mesh.num_vertices);
1961 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1962 GL_LockArrays(0, 0);
1967 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1968 GL_DepthMask(false);
1970 GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
1971 memset(&m, 0, sizeof(m));
1972 m.tex[0] = R_GetTexture(t->skin.base);
1973 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1975 surface = texturesurfacelist[texturesurfaceindex];
1976 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
1977 m.pointer_vertex = surface->mesh.data_vertex3f;
1979 GL_LockArrays(0, surface->mesh.num_vertices);
1980 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
1981 GL_LockArrays(0, 0);
1986 GL_BlendFunc(GL_ONE, GL_ONE);
1987 GL_DepthMask(false);
1989 GL_Color(r_ambient.value * (1.0f / 128.0f) * ent->colormod[0], r_ambient.value * (1.0f / 128.0f) * ent->colormod[1], r_ambient.value * (1.0f / 128.0f) * ent->colormod[2], 1);
1990 memset(&m, 0, sizeof(m));
1991 m.tex[0] = R_GetTexture(t->skin.base);
1992 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1994 surface = texturesurfacelist[texturesurfaceindex];
1995 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
1996 m.pointer_vertex = surface->mesh.data_vertex3f;
1998 GL_LockArrays(0, surface->mesh.num_vertices);
1999 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
2000 GL_LockArrays(0, 0);
2005 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2006 GL_DepthMask(false);
2008 GL_Color(1, 1, 1, 1);
2009 memset(&m, 0, sizeof(m));
2010 m.tex[0] = R_GetTexture(t->skin.glow);
2011 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2013 surface = texturesurfacelist[texturesurfaceindex];
2014 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
2015 m.pointer_vertex = surface->mesh.data_vertex3f;
2017 GL_LockArrays(0, surface->mesh.num_vertices);
2018 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
2019 GL_LockArrays(0, 0);
2025 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2026 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2027 GL_DepthMask(false);
2029 GL_Color(1, 1, 1, 1);
2030 memset(&m, 0, sizeof(m));
2031 m.tex[0] = R_GetTexture(t->skin.fog);
2032 m.pointer_color = varray_color4f;
2033 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2035 surface = texturesurfacelist[texturesurfaceindex];
2037 m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
2038 m.pointer_vertex = surface->mesh.data_vertex3f;
2040 RSurf_FogPassColors_Vertex3f_Color4f(surface->mesh.data_vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], 1, 1, surface->mesh.num_vertices, modelorg);
2041 GL_LockArrays(0, surface->mesh.num_vertices);
2042 R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
2043 GL_LockArrays(0, 0);
2046 if (t->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2047 qglEnable(GL_CULL_FACE);
2050 void R_Q3BSP_DrawFaces(entity_render_t *ent, int skyfaces)
2052 int i, j, f, flagsmask, flags;
2053 msurface_t *surface;
2054 model_t *model = ent->model;
2056 const int maxfaces = 1024;
2057 int numsurfaces = 0;
2058 msurface_t *surfacelist[1024];
2059 R_Mesh_Matrix(&ent->matrix);
2060 flagsmask = Q3SURFACEFLAG_NODRAW | Q3SURFACEFLAG_SKY;
2062 flags = Q3SURFACEFLAG_SKY;
2068 for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
2070 if (ent != r_refdef.worldentity || r_worldsurfacevisible[j])
2072 surface = model->brush.data_surfaces + j;
2073 if (t != surface->texture)
2077 R_Q3BSP_DrawFaceList(ent, t, numsurfaces, surfacelist);
2080 t = surface->texture;
2081 f = t->surfaceflags & flagsmask;
2085 if (!surface->mesh.num_triangles)
2087 surfacelist[numsurfaces++] = surface;
2088 if (numsurfaces >= maxfaces)
2090 R_Q3BSP_DrawFaceList(ent, t, numsurfaces, surfacelist);
2097 R_Q3BSP_DrawFaceList(ent, t, numsurfaces, surfacelist);
2100 void R_Q3BSP_DrawSky(entity_render_t *ent)
2102 if (r_drawcollisionbrushes.integer < 2)
2103 R_Q3BSP_DrawFaces(ent, true);
2106 void R_Q3BSP_Draw(entity_render_t *ent)
2108 if (r_drawcollisionbrushes.integer < 2)
2109 R_Q3BSP_DrawFaces(ent, false);
2110 if (r_drawcollisionbrushes.integer >= 1)
2113 model_t *model = ent->model;
2114 msurface_t *surface;
2116 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2117 GL_DepthMask(false);
2119 qglPolygonOffset(r_drawcollisionbrushes_polygonfactor.value, r_drawcollisionbrushes_polygonoffset.value);
2120 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
2121 if (brush->colbrushf && brush->colbrushf->numtriangles)
2122 R_DrawCollisionBrush(brush->colbrushf);
2123 for (i = 0, surface = model->brush.data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
2124 if (surface->mesh.num_collisiontriangles)
2125 R_Q3BSP_DrawCollisionSurface(ent, surface);
2126 qglPolygonOffset(0, 0);
2130 void R_Q3BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outclusterlist, qbyte *outclusterpvs, int *outnumclusterspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer)
2132 model_t *model = ent->model;
2133 vec3_t lightmins, lightmaxs;
2134 int t, leafindex, leafsurfaceindex, surfaceindex, triangleindex, outnumclusters = 0, outnumsurfaces = 0;
2137 msurface_t *surface;
2140 lightmins[0] = relativelightorigin[0] - lightradius;
2141 lightmins[1] = relativelightorigin[1] - lightradius;
2142 lightmins[2] = relativelightorigin[2] - lightradius;
2143 lightmaxs[0] = relativelightorigin[0] + lightradius;
2144 lightmaxs[1] = relativelightorigin[1] + lightradius;
2145 lightmaxs[2] = relativelightorigin[2] + lightradius;
2146 *outnumclusterspointer = 0;
2147 *outnumsurfacespointer = 0;
2148 memset(outclusterpvs, 0, model->brush.num_pvsclusterbytes);
2149 memset(outsurfacepvs, 0, (model->nummodelsurfaces + 7) >> 3);
2152 VectorCopy(lightmins, outmins);
2153 VectorCopy(lightmaxs, outmaxs);
2156 VectorCopy(relativelightorigin, outmins);
2157 VectorCopy(relativelightorigin, outmaxs);
2158 if (model->brush.GetPVS)
2159 pvs = model->brush.GetPVS(model, relativelightorigin);
2162 // FIXME: use BSP recursion as lights are often small
2163 for (leafindex = 0, leaf = model->brush.data_leafs;leafindex < model->brush.num_leafs;leafindex++, leaf++)
2165 if (BoxesOverlap(lightmins, lightmaxs, leaf->mins, leaf->maxs) && (pvs == NULL || CHECKPVSBIT(pvs, leaf->clusterindex)))
2167 outmins[0] = min(outmins[0], leaf->mins[0]);
2168 outmins[1] = min(outmins[1], leaf->mins[1]);
2169 outmins[2] = min(outmins[2], leaf->mins[2]);
2170 outmaxs[0] = max(outmaxs[0], leaf->maxs[0]);
2171 outmaxs[1] = max(outmaxs[1], leaf->maxs[1]);
2172 outmaxs[2] = max(outmaxs[2], leaf->maxs[2]);
2175 if (!CHECKPVSBIT(outclusterpvs, leaf->clusterindex))
2177 SETPVSBIT(outclusterpvs, leaf->clusterindex);
2178 outclusterlist[outnumclusters++] = leaf->clusterindex;
2183 for (leafsurfaceindex = 0;leafsurfaceindex < leaf->numleafsurfaces;leafsurfaceindex++)
2185 surfaceindex = leaf->firstleafsurface[leafsurfaceindex];
2186 surface = model->brush.data_surfaces + surfaceindex;
2187 if (!CHECKPVSBIT(outsurfacepvs, surfaceindex))
2189 if (BoxesOverlap(lightmins, lightmaxs, surface->mins, surface->maxs) && !(surface->texture->surfaceparms & Q3SURFACEPARM_TRANS) && !(surface->texture->surfaceflags & (Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NODRAW)) && surface->mesh.num_triangles)
2191 if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2193 for (triangleindex = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;triangleindex < surface->mesh.num_triangles;triangleindex++, t++, e += 3)
2195 v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3;
2196 v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3;
2197 v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3;
2198 if (lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
2200 SETPVSBIT(outsurfacepvs, surfaceindex);
2201 outsurfacelist[outnumsurfaces++] = surfaceindex;
2208 for (triangleindex = 0, t = surface->num_firstshadowmeshtriangle, e = model->brush.shadowmesh->element3i + t * 3;triangleindex < surface->mesh.num_triangles;triangleindex++, t++, e += 3)
2210 v[0] = model->brush.shadowmesh->vertex3f + e[0] * 3;
2211 v[1] = model->brush.shadowmesh->vertex3f + e[1] * 3;
2212 v[2] = model->brush.shadowmesh->vertex3f + e[2] * 3;
2213 if (PointInfrontOfTriangle(relativelightorigin, v[0], v[1], v[2]) && lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
2215 SETPVSBIT(outsurfacepvs, surfaceindex);
2216 outsurfacelist[outnumsurfaces++] = surfaceindex;
2228 // limit combined leaf box to light boundaries
2229 outmins[0] = max(outmins[0], lightmins[0]);
2230 outmins[1] = max(outmins[1], lightmins[1]);
2231 outmins[2] = max(outmins[2], lightmins[2]);
2232 outmaxs[0] = min(outmaxs[0], lightmaxs[0]);
2233 outmaxs[1] = min(outmaxs[1], lightmaxs[1]);
2234 outmaxs[2] = min(outmaxs[2], lightmaxs[2]);
2236 *outnumclusterspointer = outnumclusters;
2237 *outnumsurfacespointer = outnumsurfaces;
2240 void R_Q3BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist, const vec3_t lightmins, const vec3_t lightmaxs)
2242 model_t *model = ent->model;
2243 msurface_t *surface;
2244 int surfacelistindex;
2245 if (r_drawcollisionbrushes.integer < 2)
2247 R_Mesh_Matrix(&ent->matrix);
2248 R_Shadow_PrepareShadowMark(model->brush.shadowmesh->numtriangles);
2249 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
2251 surface = model->brush.data_surfaces + surfacelist[surfacelistindex];
2252 // FIXME: check some manner of surface->rendermode here?
2253 if (!(surface->texture->surfaceflags & Q3SURFACEFLAG_NODRAW) && !(surface->texture->surfaceparms & (Q3SURFACEPARM_SKY | Q3SURFACEPARM_TRANS)) && !(surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED))
2254 R_Shadow_MarkVolumeFromBox(surface->num_firstshadowmeshtriangle, surface->mesh.num_triangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, relativelightorigin, lightmins, lightmaxs, surface->mins, surface->maxs);
2256 R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, lightradius + model->radius + r_shadow_projectdistance.value, numshadowmark, shadowmarklist);
2260 void R_Q3BSP_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltolight, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz, rtexture_t *lightcubemap, vec_t ambientscale, vec_t diffusescale, vec_t specularscale, int numsurfaces, const int *surfacelist)
2262 model_t *model = ent->model;
2263 vec3_t lightmins, lightmaxs, modelorg;
2264 msurface_t *surface;
2265 int surfacelistindex;
2266 if (r_drawcollisionbrushes.integer < 2)
2268 lightmins[0] = relativelightorigin[0] - lightradius;
2269 lightmins[1] = relativelightorigin[1] - lightradius;
2270 lightmins[2] = relativelightorigin[2] - lightradius;
2271 lightmaxs[0] = relativelightorigin[0] + lightradius;
2272 lightmaxs[1] = relativelightorigin[1] + lightradius;
2273 lightmaxs[2] = relativelightorigin[2] + lightradius;
2274 R_Mesh_Matrix(&ent->matrix);
2275 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2276 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
2278 surface = model->brush.data_surfaces + surfacelist[surfacelistindex];
2279 if (r_shadow_compilingrtlight)
2281 // if compiling an rtlight, capture the mesh
2282 Mod_ShadowMesh_AddMesh(r_shadow_mempool, r_shadow_compilingrtlight->static_meshchain_light, surface->texture->skin.base, surface->texture->skin.gloss, surface->texture->skin.nmap, surface->mesh.data_vertex3f, surface->mesh.data_svector3f, surface->mesh.data_tvector3f, surface->mesh.data_normal3f, surface->mesh.data_texcoordtexture2f, surface->mesh.num_triangles, surface->mesh.data_element3i);
2284 else if ((ent != r_refdef.worldentity || r_worldsurfacevisible[surfacelist[surfacelistindex]]) && !(surface->texture->surfaceflags & Q3SURFACEFLAG_NODRAW) && surface->mesh.num_triangles)
2286 if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2287 qglDisable(GL_CULL_FACE);
2288 R_Shadow_RenderLighting(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i, surface->mesh.data_vertex3f, surface->mesh.data_svector3f, surface->mesh.data_tvector3f, surface->mesh.data_normal3f, surface->mesh.data_texcoordtexture2f, relativelightorigin, relativeeyeorigin, lightcolor, matrix_modeltolight, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, surface->texture->skin.base, surface->texture->skin.nmap, surface->texture->skin.gloss, lightcubemap, ambientscale, diffusescale, specularscale);
2289 if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2290 qglEnable(GL_CULL_FACE);
2297 static void gl_surf_start(void)
2301 static void gl_surf_shutdown(void)
2305 static void gl_surf_newmap(void)
2310 void GL_Surf_Init(void)
2313 dlightdivtable[0] = 4194304;
2314 for (i = 1;i < 32768;i++)
2315 dlightdivtable[i] = 4194304 / (i << 7);
2317 Cvar_RegisterVariable(&r_ambient);
2318 Cvar_RegisterVariable(&r_drawportals);
2319 Cvar_RegisterVariable(&r_testvis);
2320 Cvar_RegisterVariable(&r_floatbuildlightmap);
2321 Cvar_RegisterVariable(&r_detailtextures);
2322 Cvar_RegisterVariable(&r_surfaceworldnode);
2323 Cvar_RegisterVariable(&r_drawcollisionbrushes_polygonfactor);
2324 Cvar_RegisterVariable(&r_drawcollisionbrushes_polygonoffset);
2325 Cvar_RegisterVariable(&r_q3bsp_renderskydepth);
2326 Cvar_RegisterVariable(&gl_lightmaps);
2328 //R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap);