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
26 #define MAX_LIGHTMAP_SIZE 256
28 cvar_t r_ambient = {0, "r_ambient", "0"};
29 cvar_t r_drawportals = {0, "r_drawportals", "0"};
30 cvar_t r_testvis = {0, "r_testvis", "0"};
31 cvar_t r_detailtextures = {CVAR_SAVE, "r_detailtextures", "1"};
32 cvar_t r_surfaceworldnode = {0, "r_surfaceworldnode", "0"};
33 cvar_t r_drawcollisionbrushes_polygonfactor = {0, "r_drawcollisionbrushes_polygonfactor", "-1"};
34 cvar_t r_drawcollisionbrushes_polygonoffset = {0, "r_drawcollisionbrushes_polygonoffset", "0"};
35 cvar_t r_q3bsp_renderskydepth = {0, "r_q3bsp_renderskydepth", "0"};
36 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
38 // flag arrays used for visibility checking on world model
39 // (all other entities have no per-surface/per-leaf visibility checks)
40 // TODO: dynamic resize according to r_refdef.worldmodel->brush.num_clusters
41 qbyte r_pvsbits[(32768+7)>>3];
42 // TODO: dynamic resize according to r_refdef.worldmodel->brush.num_leafs
43 qbyte r_worldleafvisible[32768];
44 // TODO: dynamic resize according to r_refdef.worldmodel->brush.num_surfaces
45 qbyte r_worldsurfacevisible[262144];
51 Combine and scale multiple lightmaps into the 8.8 format in blocklights
54 static void R_BuildLightMap (const entity_render_t *ent, msurface_t *surface)
56 int smax, tmax, i, j, size, size3, maps, stride, l;
57 unsigned int *bl, scale;
58 qbyte *lightmap, *out, *stain;
59 static unsigned int intblocklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*3]; // LordHavoc: *3 for colored lighting
60 static qbyte templight[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*4];
62 // update cached lighting info
63 surface->cached_dlight = 0;
65 smax = (surface->lightmapinfo->extents[0]>>4)+1;
66 tmax = (surface->lightmapinfo->extents[1]>>4)+1;
69 lightmap = surface->lightmapinfo->samples;
71 // set to full bright if no light data
73 if (!ent->model->brushq1.lightdata)
75 for (i = 0;i < size3;i++)
81 memset(bl, 0, size*3*sizeof(unsigned int));
83 // add all the lightmaps
87 for (maps = 0;maps < MAXLIGHTMAPS && surface->lightmapinfo->styles[maps] != 255;maps++, lightmap += size3)
88 for (scale = d_lightstylevalue[surface->lightmapinfo->styles[maps]], i = 0;i < size3;i++)
89 bl[i] += lightmap[i] * scale;
93 stain = surface->lightmapinfo->stainsamples;
96 // the >> 16 shift adjusts down 8 bits to account for the stainmap
97 // scaling, and remaps the 0-65536 (2x overbright) to 0-256, it will
98 // be doubled during rendering to achieve 2x overbright
99 // (0 = 0.0, 128 = 1.0, 256 = 2.0)
100 if (ent->model->brushq1.lightmaprgba)
102 stride = (surface->lightmapinfo->lightmaptexturestride - smax) * 4;
103 for (i = 0;i < tmax;i++, out += stride)
105 for (j = 0;j < smax;j++)
107 l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
108 l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
109 l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
116 stride = (surface->lightmapinfo->lightmaptexturestride - smax) * 3;
117 for (i = 0;i < tmax;i++, out += stride)
119 for (j = 0;j < smax;j++)
121 l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
122 l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
123 l = (*bl++ * *stain++) >> 16;*out++ = min(l, 255);
128 R_UpdateTexture(surface->lightmaptexture, templight);
131 void R_StainNode (mnode_t *node, model_t *model, const vec3_t origin, float radius, const float fcolor[8])
133 float ndist, a, ratio, maxdist, maxdist2, maxdist3, invradius, sdtable[256], td, dist2;
134 msurface_t *surface, *endsurface;
135 int i, s, t, smax, tmax, smax3, impacts, impactt, stained;
139 maxdist = radius * radius;
140 invradius = 1.0f / radius;
145 ndist = PlaneDiff(origin, node->plane);
148 node = node->children[0];
153 node = node->children[1];
157 dist2 = ndist * ndist;
158 maxdist3 = maxdist - dist2;
160 if (node->plane->type < 3)
162 VectorCopy(origin, impact);
163 impact[node->plane->type] -= ndist;
167 impact[0] = origin[0] - node->plane->normal[0] * ndist;
168 impact[1] = origin[1] - node->plane->normal[1] * ndist;
169 impact[2] = origin[2] - node->plane->normal[2] * ndist;
172 for (surface = model->brush.data_surfaces + node->firstsurface, endsurface = surface + node->numsurfaces;surface < endsurface;surface++)
174 if (surface->lightmapinfo->stainsamples)
176 smax = (surface->lightmapinfo->extents[0] >> 4) + 1;
177 tmax = (surface->lightmapinfo->extents[1] >> 4) + 1;
179 impacts = DotProduct (impact, surface->lightmapinfo->texinfo->vecs[0]) + surface->lightmapinfo->texinfo->vecs[0][3] - surface->lightmapinfo->texturemins[0];
180 impactt = DotProduct (impact, surface->lightmapinfo->texinfo->vecs[1]) + surface->lightmapinfo->texinfo->vecs[1][3] - surface->lightmapinfo->texturemins[1];
182 s = bound(0, impacts, smax * 16) - impacts;
183 t = bound(0, impactt, tmax * 16) - impactt;
184 i = s * s + t * t + dist2;
188 // reduce calculations
189 for (s = 0, i = impacts; s < smax; s++, i -= 16)
190 sdtable[s] = i * i + dist2;
192 bl = surface->lightmapinfo->stainsamples;
197 for (t = 0;t < tmax;t++, i -= 16)
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 ratio = lhrandom(0.0f, 1.0f);
209 a = (fcolor[3] + ratio * fcolor[7]) * (1.0f - sqrt(sdtable[s] + td) * invradius);
210 if (a >= (1.0f / 64.0f))
214 bl[0] = (qbyte) ((float) bl[0] + a * ((fcolor[0] + ratio * fcolor[4]) - (float) bl[0]));
215 bl[1] = (qbyte) ((float) bl[1] + a * ((fcolor[1] + ratio * fcolor[5]) - (float) bl[1]));
216 bl[2] = (qbyte) ((float) bl[2] + a * ((fcolor[2] + ratio * fcolor[6]) - (float) bl[2]));
226 // force lightmap upload
228 surface->cached_dlight = true;
232 if (node->children[0]->plane)
234 if (node->children[1]->plane)
236 R_StainNode(node->children[0], model, origin, radius, fcolor);
237 node = node->children[1];
242 node = node->children[0];
246 else if (node->children[1]->plane)
248 node = node->children[1];
253 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)
257 entity_render_t *ent;
260 if (r_refdef.worldmodel == NULL || !r_refdef.worldmodel->brush.data_nodes || !r_refdef.worldmodel->brushq1.lightdata)
265 fcolor[3] = ca1 * (1.0f / 64.0f);
266 fcolor[4] = cr2 - cr1;
267 fcolor[5] = cg2 - cg1;
268 fcolor[6] = cb2 - cb1;
269 fcolor[7] = (ca2 - ca1) * (1.0f / 64.0f);
271 R_StainNode(r_refdef.worldmodel->brush.data_nodes + r_refdef.worldmodel->brushq1.hulls[0].firstclipnode, r_refdef.worldmodel, origin, radius, fcolor);
273 // look for embedded bmodels
274 for (n = 0;n < cl_num_brushmodel_entities;n++)
276 ent = &cl_entities[cl_brushmodel_entities[n]].render;
278 if (model && model->name[0] == '*')
280 Mod_CheckLoaded(model);
281 if (model->brush.data_nodes)
283 Matrix4x4_Transform(&ent->inversematrix, origin, org);
284 R_StainNode(model->brush.data_nodes + model->brushq1.hulls[0].firstclipnode, model, org, radius, fcolor);
292 =============================================================
296 =============================================================
299 static void RSurf_DeformVertices(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
302 float center[3], forward[3], right[3], up[3], v[4][3];
303 matrix4x4_t matrix1, imatrix1;
304 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
306 // a single autosprite surface can contain multiple sprites...
307 VectorClear(forward);
309 VectorSet(up, 0, 0, 1);
310 for (j = 0;j < surface->num_vertices - 3;j += 4)
313 for (i = 0;i < 4;i++)
314 VectorAdd(center, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
315 VectorScale(center, 0.25f, center);
316 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
317 Matrix4x4_FromVectors(&matrix1, (surface->groupmesh->data_normal3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_svector3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
318 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
319 for (i = 0;i < 4;i++)
320 Matrix4x4_Transform(&imatrix1, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
321 forward[0] = modelorg[0] - center[0];
322 forward[1] = modelorg[1] - center[1];
323 VectorNormalize(forward);
324 right[0] = forward[1];
325 right[1] = -forward[0];
326 for (i = 0;i < 4;i++)
327 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
330 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
332 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
333 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
334 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
335 // a single autosprite surface can contain multiple sprites...
336 for (j = 0;j < surface->num_vertices - 3;j += 4)
339 for (i = 0;i < 4;i++)
340 VectorAdd(center, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
341 VectorScale(center, 0.25f, center);
342 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
343 Matrix4x4_FromVectors(&matrix1, (surface->groupmesh->data_normal3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_svector3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
344 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
345 for (i = 0;i < 4;i++)
346 Matrix4x4_Transform(&imatrix1, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
347 for (i = 0;i < 4;i++)
348 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
352 memcpy((varray_vertex3f + 3 * surface->num_firstvertex), (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), sizeof(float[3]) * surface->num_vertices);
355 // any sort of deformvertices call is *VERY* rare, so this must be optimized
356 // to skip deformvertices quickly!
358 #define RSurf_GetVertexPointer(ent, texture, surface, modelorg) ((texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) ? (RSurf_DeformVertices(ent, texture, surface, modelorg), varray_vertex3f) : surface->groupmesh->data_vertex3f)
360 static float *RSurf_GetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
362 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
364 RSurf_DeformVertices(ent, texture, surface, modelorg);
365 return varray_vertex3f;
368 return surface->groupmesh->data_vertex3f;
372 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
374 // we don't need to set currentframe if t->animated is false because
375 // it was already set up by the texture loader for non-animating
378 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];
381 t->currentmaterialflags = t->basematerialflags;
382 t->currentalpha = ent->alpha;
383 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
384 t->currentalpha *= r_wateralpha.value;
385 if (!(ent->flags & RENDER_LIGHT))
386 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
387 if (ent->effects & EF_ADDITIVE)
388 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
389 else if (t->currentalpha < 1)
390 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
393 matrix4x4_t r_surf_waterscrollmatrix;
395 void R_UpdateAllTextureInfo(entity_render_t *ent)
398 Matrix4x4_CreateTranslate(&r_surf_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
400 for (i = 0;i < ent->model->brush.num_textures;i++)
401 R_UpdateTextureInfo(ent, ent->model->brush.data_textures + i);
404 static void R_DrawSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
407 int texturesurfaceindex;
408 const float *v, *vertex3f;
411 float f, r, g, b, a, base, colorscale;
412 const msurface_t *surface;
419 qboolean fogallpasses;
420 qboolean waterscrolling;
421 surfmesh_t *groupmesh;
422 rtexture_t *lightmaptexture;
424 texture = texture->currentframe;
425 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
427 c_faces += texturenumsurfaces;
428 // gl_lightmaps debugging mode skips normal texturing
429 if (gl_lightmaps.integer)
431 GL_BlendFunc(GL_ONE, GL_ZERO);
434 qglDisable(GL_CULL_FACE);
435 GL_Color(1, 1, 1, 1);
436 memset(&m, 0, sizeof(m));
438 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
440 surface = texturesurfacelist[texturesurfaceindex];
441 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
442 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
443 R_Mesh_ColorPointer(surface->lightmaptexture ? NULL : surface->groupmesh->data_lightmapcolor4f);
444 R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f);
445 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
446 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
449 qglEnable(GL_CULL_FACE);
452 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
453 GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT));
454 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
455 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
456 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
457 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
459 GL_BlendFunc(GL_ONE, GL_ZERO);
460 // water waterscrolling in texture matrix
461 waterscrolling = (texture->currentmaterialflags & MATERIALFLAG_WATER) && r_waterscroll.value != 0;
462 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
463 qglDisable(GL_CULL_FACE);
464 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
468 skyrendernow = false;
472 // LordHavoc: HalfLife maps have freaky skypolys...
473 //if (!ent->model->brush.ishlbsp)
475 R_Mesh_Matrix(&ent->matrix);
476 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
479 // depth-only (masking)
480 GL_ColorMask(0,0,0,0);
481 // just to make sure that braindead drivers don't draw anything
482 // despite that colormask...
483 GL_BlendFunc(GL_ZERO, GL_ONE);
488 GL_BlendFunc(GL_ONE, GL_ZERO);
492 memset(&m, 0, sizeof(m));
494 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
496 surface = texturesurfacelist[texturesurfaceindex];
497 R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f);
498 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
499 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
502 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
505 else if ((texture->currentmaterialflags & MATERIALFLAG_WATER) && r_watershader.value && gl_textureshader && !texture->skin.glow && !fogenabled && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1)
507 // NVIDIA Geforce3 distortion texture shader on water
508 float args[4] = {0.05f,0,0,0.04f};
509 memset(&m, 0, sizeof(m));
510 m.tex[0] = R_GetTexture(mod_shared_distorttexture[(int)(r_refdef.time * 16)&63]);
511 m.tex[1] = R_GetTexture(texture->skin.base);
512 m.texcombinergb[0] = GL_REPLACE;
513 m.texcombinergb[1] = GL_REPLACE;
514 Matrix4x4_CreateFromQuakeEntity(&m.texmatrix[0], 0, 0, 0, 0, 0, 0, r_watershader.value);
515 m.texmatrix[1] = r_surf_waterscrollmatrix;
518 GL_Color(1, 1, 1, texture->currentalpha);
520 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
522 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV);
523 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB);
524 qglTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, &args[0]);
525 qglEnable(GL_TEXTURE_SHADER_NV);
527 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
529 surface = texturesurfacelist[texturesurfaceindex];
530 R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
531 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
532 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
533 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
534 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
538 qglDisable(GL_TEXTURE_SHADER_NV);
539 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
542 else if (texture->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
544 // normal surface (wall or water)
546 dolightmap = !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT);
547 doambient = r_ambient.value >= (1/64.0f);
548 dodetail = r_detailtextures.integer && texture->skin.detail != NULL && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
549 doglow = texture->skin.glow != NULL;
550 dofogpass = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD);
551 fogallpasses = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
552 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
554 if (dobase && dolightmap && gl_combine.integer)
557 memset(&m, 0, sizeof(m));
558 m.tex[1] = R_GetTexture(texture->skin.base);
560 m.texmatrix[1] = r_surf_waterscrollmatrix;
561 m.texrgbscale[1] = 2;
562 m.pointer_color = varray_color4f;
565 r = ent->colormod[0] * colorscale;
566 g = ent->colormod[1] * colorscale;
567 b = ent->colormod[2] * colorscale;
568 a = texture->currentalpha;
569 base = r_ambient.value * (1.0f / 64.0f);
570 // q3bsp has no lightmap updates, so the lightstylevalue that
571 // would normally be baked into the lightmaptexture must be
572 // applied to the color
573 if (ent->model->brushq1.lightdata)
575 float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
580 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
582 surface = texturesurfacelist[texturesurfaceindex];
583 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
584 R_Mesh_VertexPointer(vertex3f);
585 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
586 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
587 if (surface->lightmaptexture)
589 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
592 R_Mesh_ColorPointer(varray_color4f);
593 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
595 VectorSubtract(v, modelorg, diff);
596 f = 1 - exp(fogdensity/DotProduct(diff, diff));
605 R_Mesh_ColorPointer(NULL);
606 GL_Color(r, g, b, a);
611 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
612 R_Mesh_ColorPointer(varray_color4f);
613 if (!surface->lightmaptexture)
615 for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4)
617 c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r;
618 c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g;
619 c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b;
620 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
624 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
626 VectorSubtract(v, modelorg, diff);
627 f = 1 - exp(fogdensity/DotProduct(diff, diff));
628 VectorScale(c, f, c);
634 R_Mesh_ColorPointer(NULL);
635 GL_Color(0, 0, 0, a);
638 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
639 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
646 memset(&m, 0, sizeof(m));
647 m.tex[0] = R_GetTexture(texture->skin.base);
649 m.texmatrix[0] = r_surf_waterscrollmatrix;
650 m.pointer_color = varray_color4f;
652 if (gl_combine.integer)
654 m.texrgbscale[0] = 4;
658 r = ent->colormod[0] * colorscale;
659 g = ent->colormod[1] * colorscale;
660 b = ent->colormod[2] * colorscale;
661 a = texture->currentalpha;
664 // q3bsp has no lightmap updates, so the lightstylevalue that
665 // would normally be baked into the lightmaptexture must be
666 // applied to the color
667 if (!ent->model->brushq1.lightdata)
669 float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
674 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
676 surface = texturesurfacelist[texturesurfaceindex];
677 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
678 R_Mesh_VertexPointer(vertex3f);
679 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
680 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
685 if (!surface->lightmapinfo)
686 VectorCopy((surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex) + i*4, c);
687 else //if (surface->lightmapinfo)
689 const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
690 float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
691 VectorMA(c, scale, lm, c);
692 if (surface->lightmapinfo->styles[1] != 255)
694 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
696 scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
697 VectorMA(c, scale, lm, c);
698 if (surface->lightmapinfo->styles[2] != 255)
701 scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
702 VectorMA(c, scale, lm, c);
703 if (surface->lightmapinfo->styles[3] != 255)
706 scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
707 VectorMA(c, scale, lm, c);
717 VectorSubtract(v, modelorg, diff);
718 f = 1 - exp(fogdensity/DotProduct(diff, diff));
719 VectorScale(c, f, c);
721 if (!surface->lightmapinfo && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
722 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
726 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
727 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
735 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
737 surface = texturesurfacelist[texturesurfaceindex];
738 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
739 R_Mesh_VertexPointer(vertex3f);
740 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
741 if (!surface->lightmapinfo && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
743 R_Mesh_ColorPointer(varray_color4f);
744 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
746 VectorSubtract(v, modelorg, diff);
747 f = 1 - exp(fogdensity/DotProduct(diff, diff));
751 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
756 R_Mesh_ColorPointer(varray_color4f);
757 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
759 VectorSubtract(v, modelorg, diff);
760 f = 1 - exp(fogdensity/DotProduct(diff, diff));
767 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
768 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
774 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
776 surface = texturesurfacelist[texturesurfaceindex];
777 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
778 R_Mesh_VertexPointer(vertex3f);
779 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
780 if (!surface->lightmaptexture && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
782 R_Mesh_ColorPointer(varray_color4f);
783 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
788 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
793 R_Mesh_ColorPointer(NULL);
794 GL_Color(r, g, b, a);
796 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
797 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
806 if (!dolightmap && dobase)
810 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], 1);
811 memset(&m, 0, sizeof(m));
812 m.tex[0] = R_GetTexture(texture->skin.base);
814 m.texmatrix[0] = r_surf_waterscrollmatrix;
816 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
818 surface = texturesurfacelist[texturesurfaceindex];
819 R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
820 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
821 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
822 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
826 if (r_lightmapintensity <= 0 && dolightmap && dobase)
830 GL_Color(0, 0, 0, 1);
831 memset(&m, 0, sizeof(m));
833 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
835 surface = texturesurfacelist[texturesurfaceindex];
836 R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
837 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
838 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
842 if (r_textureunits.integer >= 2 && gl_combine.integer && dolightmap && dobase)
844 // dualtexture combine
845 GL_BlendFunc(GL_ONE, GL_ZERO);
849 memset(&m, 0, sizeof(m));
850 m.tex[1] = R_GetTexture(texture->skin.base);
852 m.texmatrix[1] = r_surf_waterscrollmatrix;
853 m.texrgbscale[1] = 2;
855 r = ent->colormod[0] * r_lightmapintensity;
856 g = ent->colormod[1] * r_lightmapintensity;
857 b = ent->colormod[2] * r_lightmapintensity;
858 GL_Color(r, g, b, 1);
859 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
861 R_Mesh_VertexPointer(varray_vertex3f);
862 if (r == 1 && g == 1 && b == 1)
864 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
866 surface = texturesurfacelist[texturesurfaceindex];
867 RSurf_DeformVertices(ent, texture, surface, modelorg);
868 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
869 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
870 if (surface->lightmaptexture)
872 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
873 R_Mesh_ColorPointer(NULL);
875 else //if (r == 1 && g == 1 && b == 1)
877 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
878 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
880 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
881 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
887 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
889 surface = texturesurfacelist[texturesurfaceindex];
890 RSurf_DeformVertices(ent, texture, surface, modelorg);
891 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
892 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
893 if (surface->lightmaptexture)
895 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
896 R_Mesh_ColorPointer(NULL);
900 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
901 R_Mesh_ColorPointer(varray_color4f);
902 for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4)
904 c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r;
905 c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g;
906 c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b;
907 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3];
910 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
911 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
918 if (r == 1 && g == 1 && b == 1)
921 // experimental direct state calls for measuring
922 // R_Mesh_ call overhead, do not use!
923 R_Mesh_VertexPointer(varray_vertex3f);
924 R_Mesh_TexCoordPointer(0, 2, varray_texcoord2f[0]);
925 R_Mesh_TexCoordPointer(1, 2, varray_texcoord2f[1]);
926 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
927 R_Mesh_ColorPointer(varray_color4f);
928 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
930 surface = texturesurfacelist[texturesurfaceindex];
931 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), surface->groupmesh->data_vertex3f);
932 qglClientActiveTexture(GL_TEXTURE0_ARB);
933 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), surface->groupmesh->data_texcoordlightmap2f);
934 qglClientActiveTexture(GL_TEXTURE1_ARB);
935 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), surface->groupmesh->data_texcoordtexture2f);
936 if (surface->lightmaptexture)
938 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
939 qglDisableClientState(GL_COLOR_ARRAY);
940 qglColor4f(r, g, b, 1);
942 else //if (r == 1 && g == 1 && b == 1)
944 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
945 qglEnableClientState(GL_COLOR_ARRAY);
946 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), surface->groupmesh->data_lightmapcolor4f);
948 qglLockArraysEXT(0, surface->num_vertices);
949 qglDrawRangeElements(GL_TRIANGLES, surface->num_firstvertex, surface->num_firstvertex + surface->num_vertices, surface->num_triangles * 3, GL_UNSIGNED_INT, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
950 qglUnlockArraysEXT();
954 lightmaptexture = NULL;
955 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
957 surface = texturesurfacelist[texturesurfaceindex];
958 if (groupmesh != surface->groupmesh)
960 groupmesh = surface->groupmesh;
961 R_Mesh_VertexPointer(groupmesh->data_vertex3f);
962 R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordlightmap2f);
963 R_Mesh_TexCoordPointer(1, 2, groupmesh->data_texcoordtexture2f);
964 if (!lightmaptexture)
965 R_Mesh_ColorPointer(groupmesh->data_lightmapcolor4f);
967 if (lightmaptexture != surface->lightmaptexture)
969 lightmaptexture = surface->lightmaptexture;
972 R_Mesh_TexBind(0, R_GetTexture(lightmaptexture));
973 R_Mesh_ColorPointer(NULL);
975 else //if (r == 1 && g == 1 && b == 1)
977 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
978 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
981 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
982 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
989 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
991 surface = texturesurfacelist[texturesurfaceindex];
992 R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f);
993 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
994 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
995 if (surface->lightmaptexture)
997 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
998 R_Mesh_ColorPointer(NULL);
1002 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1003 R_Mesh_ColorPointer(varray_color4f);
1004 for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4)
1006 c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r;
1007 c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g;
1008 c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b;
1009 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3];
1012 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1013 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1014 GL_LockArrays(0, 0);
1022 GL_BlendFunc(GL_ONE, GL_ZERO);
1024 GL_Color(1, 1, 1, 1);
1025 memset(&m, 0, sizeof(m));
1027 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
1029 R_Mesh_VertexPointer(varray_vertex3f);
1030 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1032 surface = texturesurfacelist[texturesurfaceindex];
1033 RSurf_DeformVertices(ent, texture, surface, modelorg);
1034 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1035 if (surface->lightmaptexture)
1037 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1038 R_Mesh_ColorPointer(NULL);
1040 else //if (r == 1 && g == 1 && b == 1)
1042 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1043 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
1045 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1046 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1047 GL_LockArrays(0, 0);
1053 lightmaptexture = NULL;
1054 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1056 surface = texturesurfacelist[texturesurfaceindex];
1057 if (groupmesh != surface->groupmesh)
1059 groupmesh = surface->groupmesh;
1060 R_Mesh_VertexPointer(groupmesh->data_vertex3f);
1061 R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordlightmap2f);
1062 if (!lightmaptexture)
1063 R_Mesh_ColorPointer(groupmesh->data_lightmapcolor4f);
1065 if (lightmaptexture != surface->lightmaptexture)
1067 lightmaptexture = surface->lightmaptexture;
1068 if (lightmaptexture)
1070 R_Mesh_TexBind(0, R_GetTexture(lightmaptexture));
1071 R_Mesh_ColorPointer(NULL);
1073 else //if (r == 1 && g == 1 && b == 1)
1075 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1076 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
1079 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1080 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1081 GL_LockArrays(0, 0);
1087 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1088 GL_DepthMask(false);
1089 GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
1090 memset(&m, 0, sizeof(m));
1091 m.tex[0] = R_GetTexture(texture->skin.base);
1093 m.texmatrix[0] = r_surf_waterscrollmatrix;
1095 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
1097 R_Mesh_VertexPointer(varray_vertex3f);
1098 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1100 surface = texturesurfacelist[texturesurfaceindex];
1101 RSurf_DeformVertices(ent, texture, surface, modelorg);
1102 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1103 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1104 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1105 GL_LockArrays(0, 0);
1111 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1113 surface = texturesurfacelist[texturesurfaceindex];
1114 if (groupmesh != surface->groupmesh)
1116 groupmesh = surface->groupmesh;
1117 R_Mesh_VertexPointer(groupmesh->data_vertex3f);
1118 R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordtexture2f);
1120 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1121 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1122 GL_LockArrays(0, 0);
1130 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1131 GL_DepthMask(false);
1132 memset(&m, 0, sizeof(m));
1133 m.tex[0] = R_GetTexture(texture->skin.base);
1135 m.texmatrix[0] = r_surf_waterscrollmatrix;
1136 m.pointer_color = varray_color4f;
1138 if (gl_combine.integer)
1140 m.texrgbscale[0] = 4;
1141 colorscale *= 0.25f;
1144 base = r_ambient.value * (1.0f / 64.0f);
1145 r = ent->colormod[0] * colorscale * base;
1146 g = ent->colormod[1] * colorscale * base;
1147 b = ent->colormod[2] * colorscale * base;
1148 a = texture->currentalpha;
1149 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1151 surface = texturesurfacelist[texturesurfaceindex];
1152 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
1153 R_Mesh_VertexPointer(vertex3f);
1154 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1155 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1162 VectorSubtract(v, modelorg, diff);
1163 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1164 VectorScale(c, f, c);
1166 if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1167 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
1171 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1172 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1173 GL_LockArrays(0, 0);
1178 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1179 GL_DepthMask(false);
1180 GL_Color(1, 1, 1, 1);
1181 memset(&m, 0, sizeof(m));
1182 m.tex[0] = R_GetTexture(texture->skin.detail);
1184 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1186 surface = texturesurfacelist[texturesurfaceindex];
1187 R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
1188 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoorddetail2f);
1189 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1190 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1191 GL_LockArrays(0, 0);
1196 // if glow was not already done using multitexture, do it now.
1197 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1198 GL_DepthMask(false);
1199 memset(&m, 0, sizeof(m));
1200 m.tex[0] = R_GetTexture(texture->skin.glow);
1202 m.texmatrix[0] = r_surf_waterscrollmatrix;
1203 m.pointer_color = varray_color4f;
1206 r = ent->colormod[0] * colorscale;
1207 g = ent->colormod[1] * colorscale;
1208 b = ent->colormod[2] * colorscale;
1209 a = texture->currentalpha;
1212 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1214 surface = texturesurfacelist[texturesurfaceindex];
1215 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
1216 R_Mesh_VertexPointer(vertex3f);
1217 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1218 R_Mesh_ColorPointer(varray_color4f);
1219 if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1221 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1223 VectorSubtract(v, modelorg, diff);
1224 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1228 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
1233 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1235 VectorSubtract(v, modelorg, diff);
1236 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1243 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1244 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1245 GL_LockArrays(0, 0);
1250 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1252 surface = texturesurfacelist[texturesurfaceindex];
1253 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
1254 R_Mesh_VertexPointer(vertex3f);
1255 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1256 if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1258 R_Mesh_ColorPointer(varray_color4f);
1259 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1264 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
1269 R_Mesh_ColorPointer(NULL);
1270 GL_Color(r, g, b, a);
1272 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1273 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1274 GL_LockArrays(0, 0);
1280 // if this is opaque use alpha blend which will darken the earlier
1283 // if this is an alpha blended material, all the earlier passes
1284 // were darkened by fog already, so we only need to add the fog
1285 // color ontop through the fog mask texture
1287 // if this is an additive blended material, all the earlier passes
1288 // were darkened by fog already, and we should not add fog color
1289 // (because the background was not darkened, there is no fog color
1290 // that was lost behind it).
1292 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1294 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1295 GL_DepthMask(false);
1296 memset(&m, 0, sizeof(m));
1297 m.tex[0] = R_GetTexture(texture->skin.fog);
1299 m.texmatrix[0] = r_surf_waterscrollmatrix;
1304 a = texture->currentalpha;
1305 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1307 surface = texturesurfacelist[texturesurfaceindex];
1308 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
1309 R_Mesh_VertexPointer(vertex3f);
1310 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1311 R_Mesh_ColorPointer(varray_color4f);
1312 //RSurf_FogPassColors_Vertex3f_Color4f((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], texture->currentalpha, 1, surface->num_vertices, modelorg);
1313 if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1315 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1317 VectorSubtract(v, modelorg, diff);
1318 f = exp(fogdensity/DotProduct(diff, diff));
1322 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * f * a;
1327 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1329 VectorSubtract(v, modelorg, diff);
1330 f = exp(fogdensity/DotProduct(diff, diff));
1337 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1338 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1339 GL_LockArrays(0, 0);
1343 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1344 qglEnable(GL_CULL_FACE);
1347 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
1349 const entity_render_t *ent = calldata1;
1350 const msurface_t *surface = ent->model->brush.data_surfaces + calldata2;
1354 texture = surface->texture;
1355 if (texture->basematerialflags & MATERIALFLAG_SKY)
1356 return; // transparent sky is too difficult
1357 R_UpdateTextureInfo(ent, texture);
1359 R_Mesh_Matrix(&ent->matrix);
1360 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
1361 R_DrawSurfaceList(ent, texture, 1, &surface, modelorg);
1364 void R_QueueSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1366 int texturesurfaceindex;
1367 const msurface_t *surface;
1368 vec3_t tempcenter, center;
1369 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
1371 // drawing sky transparently would be too difficult
1372 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
1374 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1376 surface = texturesurfacelist[texturesurfaceindex];
1377 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
1378 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
1379 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
1380 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
1381 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->brush.data_surfaces);
1386 R_DrawSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
1389 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
1391 int i, j, f, flagsmask;
1392 msurface_t *surface, **surfacechain;
1393 texture_t *t, *texture;
1394 model_t *model = ent->model;
1396 const int maxsurfacelist = 1024;
1397 int numsurfacelist = 0;
1398 const msurface_t *surfacelist[1024];
1401 R_Mesh_Matrix(&ent->matrix);
1402 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
1404 // update light styles
1405 if (!skysurfaces && model->brushq1.light_styleupdatechains)
1407 for (i = 0;i < model->brushq1.light_styles;i++)
1409 if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
1411 model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
1412 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
1413 for (;(surface = *surfacechain);surfacechain++)
1414 surface->cached_dlight = true;
1419 R_UpdateAllTextureInfo(ent);
1420 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
1425 if (ent == r_refdef.worldentity)
1427 for (i = 0, j = model->firstmodelsurface, surface = model->brush.data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
1429 if (!r_worldsurfacevisible[j])
1431 if (t != surface->texture)
1435 R_QueueSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
1438 t = surface->texture;
1439 f = t->currentmaterialflags & flagsmask;
1440 texture = t->currentframe;
1442 if (f && surface->num_triangles)
1444 // if lightmap parameters changed, rebuild lightmap texture
1445 if (surface->cached_dlight && surface->lightmapinfo->samples)
1446 R_BuildLightMap(ent, surface);
1447 // add face to draw list
1448 surfacelist[numsurfacelist++] = surface;
1449 if (numsurfacelist >= maxsurfacelist)
1451 R_QueueSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
1459 for (i = 0, j = model->firstmodelsurface, surface = model->brush.data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
1461 if (t != surface->texture)
1465 R_QueueSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
1468 t = surface->texture;
1469 f = t->currentmaterialflags & flagsmask;
1470 texture = t->currentframe;
1472 if (f && surface->num_triangles)
1474 // if lightmap parameters changed, rebuild lightmap texture
1475 if (surface->cached_dlight && surface->lightmapinfo->samples)
1476 R_BuildLightMap(ent, surface);
1477 // add face to draw list
1478 surfacelist[numsurfacelist++] = surface;
1479 if (numsurfacelist >= maxsurfacelist)
1481 R_QueueSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
1488 R_QueueSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
1491 static void R_DrawPortal_Callback(const void *calldata1, int calldata2)
1496 const mportal_t *portal = calldata1;
1497 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1498 GL_DepthMask(false);
1500 R_Mesh_Matrix(&r_identitymatrix);
1502 memset(&m, 0, sizeof(m));
1503 m.pointer_vertex = varray_vertex3f;
1507 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f),
1508 ((i & 0x0038) >> 3) * (1.0f / 7.0f),
1509 ((i & 0x01C0) >> 6) * (1.0f / 7.0f),
1511 if (PlaneDiff(r_vieworigin, (&portal->plane)) < 0)
1513 for (i = portal->numpoints - 1, v = varray_vertex3f;i >= 0;i--, v += 3)
1514 VectorCopy(portal->points[i].position, v);
1517 for (i = 0, v = varray_vertex3f;i < portal->numpoints;i++, v += 3)
1518 VectorCopy(portal->points[i].position, v);
1519 GL_LockArrays(0, portal->numpoints);
1520 R_Mesh_Draw(0, portal->numpoints, portal->numpoints - 2, polygonelements);
1521 GL_LockArrays(0, 0);
1524 // LordHavoc: this is just a nice debugging tool, very slow
1525 static void R_DrawPortals(void)
1527 int i, leafnum;//, portalnum;
1530 model_t *model = r_refdef.worldmodel;
1533 for (leafnum = 0;leafnum < r_refdef.worldmodel->brush.num_leafs;leafnum++)
1535 if (r_worldleafvisible[leafnum])
1537 //for (portalnum = 0, portal = model->brush.data_portals;portalnum < model->brush.num_portals;portalnum++, portal++)
1538 for (portal = r_refdef.worldmodel->brush.data_leafs[leafnum].portals;portal;portal = portal->next)
1540 if (portal->numpoints <= POLYGONELEMENTS_MAXPOINTS)
1541 if (!R_CullBox(portal->mins, portal->maxs))
1543 VectorClear(center);
1544 for (i = 0;i < portal->numpoints;i++)
1545 VectorAdd(center, portal->points[i].position, center);
1546 f = ixtable[portal->numpoints];
1547 VectorScale(center, f, center);
1548 //R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, portal, portalnum);
1549 R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, portal, leafnum);
1556 static void R_DrawCollisionBrush(colbrushf_t *brush)
1560 memset(&m, 0, sizeof(m));
1561 m.pointer_vertex = brush->points->v;
1563 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
1564 GL_Color((i & 31) * (1.0f / 32.0f), ((i >> 5) & 31) * (1.0f / 32.0f), ((i >> 10) & 31) * (1.0f / 32.0f), 0.2f);
1565 GL_LockArrays(0, brush->numpoints);
1566 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
1567 GL_LockArrays(0, 0);
1570 static void R_DrawCollisionSurface(entity_render_t *ent, msurface_t *surface)
1574 if (!surface->num_collisiontriangles)
1576 memset(&m, 0, sizeof(m));
1577 m.pointer_vertex = surface->data_collisionvertex3f;
1579 i = (int)(((size_t)surface) / sizeof(msurface_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, surface->num_collisionvertices);
1582 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
1583 GL_LockArrays(0, 0);
1586 void R_WorldVisibility(void)
1591 model_t *model = r_refdef.worldmodel;
1596 // if possible find the leaf the view origin is in
1597 viewleaf = model->brush.PointInLeaf ? model->brush.PointInLeaf(model, r_vieworigin) : NULL;
1598 // if possible fetch the visible cluster bits
1599 if (model->brush.FatPVS)
1600 model->brush.FatPVS(model, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
1602 // clear the visible surface and leaf flags arrays
1603 memset(r_worldsurfacevisible, 0, model->brush.num_surfaces);
1604 memset(r_worldleafvisible, 0, model->brush.num_leafs);
1606 // if the user prefers surfaceworldnode (testing?) or the viewleaf could
1607 // not be found, or the viewleaf is not part of the visible world
1608 // (floating around in the void), use the pvs method
1609 if (r_surfaceworldnode.integer || !viewleaf || viewleaf->clusterindex < 0)
1612 // similar to quake's RecursiveWorldNode but without cache misses
1613 for (j = 0, leaf = model->brush.data_leafs;j < model->brush.num_leafs;j++, leaf++)
1615 // if leaf is in current pvs and on the screen, mark its surfaces
1616 if (CHECKPVSBIT(r_pvsbits, leaf->clusterindex) && !R_CullBox(leaf->mins, leaf->maxs))
1619 r_worldleafvisible[j] = true;
1620 if (leaf->numleafsurfaces)
1621 for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
1622 r_worldsurfacevisible[*mark] = true;
1630 mleaf_t *leafstack[8192];
1632 // follows portals leading outward from viewleaf, does not venture
1633 // offscreen or into leafs that are not visible, faster than Quake's
1634 // RecursiveWorldNode and vastly better in unvised maps, often culls a
1635 // lot of surface that pvs alone would miss
1636 leafstack[0] = viewleaf;
1638 while (leafstackpos)
1641 leaf = leafstack[--leafstackpos];
1642 r_worldleafvisible[leaf - model->brush.data_leafs] = true;
1643 // mark any surfaces bounding this leaf
1644 if (leaf->numleafsurfaces)
1645 for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
1646 r_worldsurfacevisible[*mark] = true;
1647 // follow portals into other leafs
1649 // if viewer is behind portal (portal faces outward into the scene)
1650 // and the portal polygon's bounding box is on the screen
1651 // and the leaf has not been visited yet
1652 // and the leaf is visible in the pvs
1653 // (the first two checks won't cause as many cache misses as the leaf checks)
1654 for (p = leaf->portals;p;p = p->next)
1655 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))
1656 leafstack[leafstackpos++] = p->past;
1660 if (r_drawportals.integer)
1664 void R_Q1BSP_DrawSky(entity_render_t *ent)
1666 if (ent->model == NULL)
1668 if (r_drawcollisionbrushes.integer < 2)
1669 R_DrawSurfaces(ent, true);
1672 void R_Q1BSP_Draw(entity_render_t *ent)
1674 if (ent->model == NULL)
1677 if (r_drawcollisionbrushes.integer < 2)
1678 R_DrawSurfaces(ent, false);
1679 if (r_drawcollisionbrushes.integer >= 1 && ent->model->brush.num_brushes)
1682 model_t *model = ent->model;
1683 msurface_t *surface;
1685 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1686 GL_DepthMask(false);
1688 qglPolygonOffset(r_drawcollisionbrushes_polygonfactor.value, r_drawcollisionbrushes_polygonoffset.value);
1689 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
1690 if (brush->colbrushf && brush->colbrushf->numtriangles)
1691 R_DrawCollisionBrush(brush->colbrushf);
1692 for (i = 0, surface = model->brush.data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
1693 if (surface->num_collisiontriangles)
1694 R_DrawCollisionSurface(ent, surface);
1695 qglPolygonOffset(0, 0);
1699 typedef struct r_q1bsp_getlightinfo_s
1702 vec3_t relativelightorigin;
1707 int *outsurfacelist;
1708 qbyte *outsurfacepvs;
1716 r_q1bsp_getlightinfo_t;
1718 void R_Q1BSP_RecursiveGetLightInfo(r_q1bsp_getlightinfo_t *info, mnode_t *node)
1724 if (!BoxesOverlap(info->lightmins, info->lightmaxs, node->mins, node->maxs))
1728 sides = BoxOnPlaneSide(info->lightmins, info->lightmaxs, node->plane) - 1;
1731 R_Q1BSP_RecursiveGetLightInfo(info, node->children[0]);
1732 node = node->children[1];
1735 node = node->children[sides];
1737 leaf = (mleaf_t *)node;
1738 if (info->pvs == NULL || CHECKPVSBIT(info->pvs, leaf->clusterindex))
1740 info->outmins[0] = min(info->outmins[0], leaf->mins[0]);
1741 info->outmins[1] = min(info->outmins[1], leaf->mins[1]);
1742 info->outmins[2] = min(info->outmins[2], leaf->mins[2]);
1743 info->outmaxs[0] = max(info->outmaxs[0], leaf->maxs[0]);
1744 info->outmaxs[1] = max(info->outmaxs[1], leaf->maxs[1]);
1745 info->outmaxs[2] = max(info->outmaxs[2], leaf->maxs[2]);
1746 if (info->outleafpvs)
1748 int leafindex = leaf - info->model->brush.data_leafs;
1749 if (!CHECKPVSBIT(info->outleafpvs, leafindex))
1751 SETPVSBIT(info->outleafpvs, leafindex);
1752 info->outleaflist[info->outnumleafs++] = leafindex;
1755 if (info->outsurfacepvs)
1757 int leafsurfaceindex;
1758 for (leafsurfaceindex = 0;leafsurfaceindex < leaf->numleafsurfaces;leafsurfaceindex++)
1760 int surfaceindex = leaf->firstleafsurface[leafsurfaceindex];
1761 if (!CHECKPVSBIT(info->outsurfacepvs, surfaceindex))
1763 msurface_t *surface = info->model->brush.data_surfaces + surfaceindex;
1764 if (BoxesOverlap(info->lightmins, info->lightmaxs, surface->mins, surface->maxs))
1765 if ((surface->texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL)
1767 int triangleindex, t;
1770 for (triangleindex = 0, t = surface->num_firstshadowmeshtriangle, e = info->model->brush.shadowmesh->element3i + t * 3;triangleindex < surface->num_triangles;triangleindex++, t++, e += 3)
1772 v[0] = info->model->brush.shadowmesh->vertex3f + e[0] * 3;
1773 v[1] = info->model->brush.shadowmesh->vertex3f + e[1] * 3;
1774 v[2] = info->model->brush.shadowmesh->vertex3f + e[2] * 3;
1775 if (PointInfrontOfTriangle(info->relativelightorigin, v[0], v[1], v[2]) && info->lightmaxs[0] > min(v[0][0], min(v[1][0], v[2][0])) && info->lightmins[0] < max(v[0][0], max(v[1][0], v[2][0])) && info->lightmaxs[1] > min(v[0][1], min(v[1][1], v[2][1])) && info->lightmins[1] < max(v[0][1], max(v[1][1], v[2][1])) && info->lightmaxs[2] > min(v[0][2], min(v[1][2], v[2][2])) && info->lightmins[2] < max(v[0][2], max(v[1][2], v[2][2])))
1777 SETPVSBIT(info->outsurfacepvs, surfaceindex);
1778 info->outsurfacelist[info->outnumsurfaces++] = surfaceindex;
1789 void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, qbyte *outleafpvs, int *outnumleafspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer)
1791 r_q1bsp_getlightinfo_t info;
1792 VectorCopy(relativelightorigin, info.relativelightorigin);
1793 info.lightradius = lightradius;
1794 info.lightmins[0] = info.relativelightorigin[0] - info.lightradius;
1795 info.lightmins[1] = info.relativelightorigin[1] - info.lightradius;
1796 info.lightmins[2] = info.relativelightorigin[2] - info.lightradius;
1797 info.lightmaxs[0] = info.relativelightorigin[0] + info.lightradius;
1798 info.lightmaxs[1] = info.relativelightorigin[1] + info.lightradius;
1799 info.lightmaxs[2] = info.relativelightorigin[2] + info.lightradius;
1800 if (ent->model == NULL)
1802 VectorCopy(info.lightmins, outmins);
1803 VectorCopy(info.lightmaxs, outmaxs);
1804 *outnumleafspointer = 0;
1805 *outnumsurfacespointer = 0;
1808 info.model = ent->model;
1809 info.outleaflist = outleaflist;
1810 info.outleafpvs = outleafpvs;
1811 info.outnumleafs = 0;
1812 info.outsurfacelist = outsurfacelist;
1813 info.outsurfacepvs = outsurfacepvs;
1814 info.outnumsurfaces = 0;
1815 VectorCopy(info.relativelightorigin, info.outmins);
1816 VectorCopy(info.relativelightorigin, info.outmaxs);
1817 memset(outleafpvs, 0, (info.model->brush.num_leafs + 7) >> 3);
1818 memset(outsurfacepvs, 0, (info.model->nummodelsurfaces + 7) >> 3);
1819 if (info.model->brush.GetPVS)
1820 info.pvs = info.model->brush.GetPVS(info.model, info.relativelightorigin);
1823 R_UpdateAllTextureInfo(ent);
1824 if (r_shadow_compilingrtlight)
1826 // use portal recursion for exact light volume culling, and exact surface checking
1827 Portal_Visibility(info.model, info.relativelightorigin, info.outleaflist, info.outleafpvs, &info.outnumleafs, info.outsurfacelist, info.outsurfacepvs, &info.outnumsurfaces, NULL, 0, true, info.lightmins, info.lightmaxs, info.outmins, info.outmaxs);
1829 else if (r_shadow_realtime_dlight_portalculling.integer)
1831 // use portal recursion for exact light volume culling, but not the expensive exact surface checking
1832 Portal_Visibility(info.model, info.relativelightorigin, info.outleaflist, info.outleafpvs, &info.outnumleafs, info.outsurfacelist, info.outsurfacepvs, &info.outnumsurfaces, NULL, 0, r_shadow_realtime_dlight_portalculling.integer >= 2, info.lightmins, info.lightmaxs, info.outmins, info.outmaxs);
1836 // use BSP recursion as lights are often small
1837 R_Q1BSP_RecursiveGetLightInfo(&info, info.model->brush.data_nodes);
1840 // limit combined leaf box to light boundaries
1841 outmins[0] = max(info.outmins[0] - 1, info.lightmins[0]);
1842 outmins[1] = max(info.outmins[1] - 1, info.lightmins[1]);
1843 outmins[2] = max(info.outmins[2] - 1, info.lightmins[2]);
1844 outmaxs[0] = min(info.outmaxs[0] + 1, info.lightmaxs[0]);
1845 outmaxs[1] = min(info.outmaxs[1] + 1, info.lightmaxs[1]);
1846 outmaxs[2] = min(info.outmaxs[2] + 1, info.lightmaxs[2]);
1848 *outnumleafspointer = info.outnumleafs;
1849 *outnumsurfacespointer = info.outnumsurfaces;
1852 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)
1854 model_t *model = ent->model;
1855 msurface_t *surface;
1856 int surfacelistindex;
1857 if (r_drawcollisionbrushes.integer < 2)
1859 R_Shadow_PrepareShadowMark(model->brush.shadowmesh->numtriangles);
1860 if (!r_shadow_compilingrtlight)
1861 R_UpdateAllTextureInfo(ent);
1862 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
1864 surface = model->brush.data_surfaces + surfacelist[surfacelistindex];
1865 if ((surface->texture->currentmaterialflags & (MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_WALL)) != MATERIALFLAG_WALL)
1867 if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1869 R_Shadow_MarkVolumeFromBox(surface->num_firstshadowmeshtriangle, surface->num_triangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, relativelightorigin, lightmins, lightmaxs, surface->mins, surface->maxs);
1871 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);
1875 void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolor, int numsurfaces, const int *surfacelist)
1877 model_t *model = ent->model;
1878 msurface_t *surface;
1880 int surfacelistindex;
1881 if (r_drawcollisionbrushes.integer < 2)
1883 R_Mesh_Matrix(&ent->matrix);
1884 if (!r_shadow_compilingrtlight)
1885 R_UpdateAllTextureInfo(ent);
1886 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
1888 surface = model->brush.data_surfaces + surfacelist[surfacelistindex];
1889 if (surface->texture->basematerialflags & MATERIALFLAG_NODRAW || !surface->num_triangles)
1891 if (r_shadow_compilingrtlight)
1893 // if compiling an rtlight, capture the mesh
1894 t = surface->texture;
1895 if ((t->basematerialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL)
1900 float *lightmins, *lightmaxs, *v[3], *vertex3f;
1901 e = surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle;
1902 vertex3f = surface->groupmesh->data_vertex3f;
1903 lightmins = r_shadow_compilingrtlight->cullmins;
1904 lightmaxs = r_shadow_compilingrtlight->cullmaxs;
1905 for (tri = 0;tri < surface->num_triangles;tri++, e += 3)
1907 v[0] = vertex3f + e[0] * 3;
1908 v[1] = vertex3f + e[1] * 3;
1909 v[2] = vertex3f + e[2] * 3;
1910 if (PointInfrontOfTriangle(r_shadow_compilingrtlight->shadoworigin, 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])))
1911 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->groupmesh->data_vertex3f, surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, surface->groupmesh->data_texcoordtexture2f, 1, e);
1914 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->groupmesh->data_vertex3f, surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, surface->groupmesh->data_texcoordtexture2f, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1918 else if (ent != r_refdef.worldentity || r_worldsurfacevisible[surfacelist[surfacelistindex]])
1920 t = surface->texture->currentframe;
1921 // FIXME: transparent surfaces need to be lit later
1922 if ((t->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL)
1924 if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1925 qglDisable(GL_CULL_FACE);
1926 R_Shadow_RenderLighting(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle), surface->groupmesh->data_vertex3f, surface->groupmesh->data_svector3f, surface->groupmesh->data_tvector3f, surface->groupmesh->data_normal3f, surface->groupmesh->data_texcoordtexture2f, lightcolor, vec3_origin, vec3_origin, t->skin.base, NULL, NULL, t->skin.nmap, t->skin.gloss);
1927 if (surface->texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1928 qglEnable(GL_CULL_FACE);
1936 static void gl_surf_start(void)
1940 static void gl_surf_shutdown(void)
1944 static void gl_surf_newmap(void)
1949 void GL_Surf_Init(void)
1952 Cvar_RegisterVariable(&r_ambient);
1953 Cvar_RegisterVariable(&r_drawportals);
1954 Cvar_RegisterVariable(&r_testvis);
1955 Cvar_RegisterVariable(&r_detailtextures);
1956 Cvar_RegisterVariable(&r_surfaceworldnode);
1957 Cvar_RegisterVariable(&r_drawcollisionbrushes_polygonfactor);
1958 Cvar_RegisterVariable(&r_drawcollisionbrushes_polygonoffset);
1959 Cvar_RegisterVariable(&r_q3bsp_renderskydepth);
1960 Cvar_RegisterVariable(&gl_lightmaps);
1962 //R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap);