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.
26 // used for dlight push checking and other things
31 matrix4x4_t r_identitymatrix;
33 renderstats_t renderstats;
35 // true during envmap command capture
38 // maximum visible distance (recalculated from world box each frame)
40 // brightness of world lightmaps and related lighting
41 // (often reduced when world rtlights are enabled)
42 float r_lightmapintensity;
43 // whether to draw world lights realtime, dlights realtime, and their shadows
45 qboolean r_rtworldshadows;
47 qboolean r_rtdlightshadows;
50 // forces all rendering to draw triangle outlines
65 matrix4x4_t r_view_matrix;
72 cvar_t r_showtris = {0, "r_showtris", "0"};
73 cvar_t r_shownormals = {0, "r_shownormals", "0"};
74 cvar_t r_drawentities = {0, "r_drawentities","1"};
75 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
76 cvar_t r_speeds = {0, "r_speeds","0"};
77 cvar_t r_fullbright = {0, "r_fullbright","0"};
78 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
79 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
80 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
81 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
83 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
84 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
85 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
86 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
87 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
88 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
89 cvar_t gl_fogend = {0, "gl_fogend","0"};
91 cvar_t r_textureunits = {0, "r_textureunits", "32"};
93 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
94 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
95 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
97 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0"};
98 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5"};
99 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4"};
100 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
101 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2"};
103 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1"};
105 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0"};
107 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
109 cvar_t r_test = {0, "r_test", "0"}; // used for testing renderer code changes, otherwise does nothing
111 rtexturepool_t *r_main_texturepool;
112 rtexture_t *r_bloom_texture_screen;
113 rtexture_t *r_bloom_texture_bloom;
114 rtexture_t *r_texture_blanknormalmap;
115 rtexture_t *r_texture_white;
116 rtexture_t *r_texture_black;
117 rtexture_t *r_texture_notexture;
118 rtexture_t *r_texture_whitecube;
119 rtexture_t *r_texture_normalizationcube;
120 rtexture_t *r_texture_fogattenuation;
121 rtexture_t *r_texture_fogintensity;
123 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
126 for (i = 0;i < verts;i++)
137 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
140 for (i = 0;i < verts;i++)
155 vec_t fogtabledistmultiplier;
156 float fogtable[FOGTABLEWIDTH];
157 float fog_density, fog_red, fog_green, fog_blue;
159 qboolean oldgl_fogenable;
160 void R_UpdateFog(void)
162 if (gamemode == GAME_NEHAHRA)
164 if (gl_fogenable.integer)
166 oldgl_fogenable = true;
167 fog_density = gl_fogdensity.value;
168 fog_red = gl_fogred.value;
169 fog_green = gl_foggreen.value;
170 fog_blue = gl_fogblue.value;
172 else if (oldgl_fogenable)
174 oldgl_fogenable = false;
183 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
184 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
185 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
190 fogdensity = -4000.0f / (fog_density * fog_density);
191 // this is the point where the fog reaches 0.9986 alpha, which we
192 // consider a good enough cutoff point for the texture
193 // (0.9986 * 256 == 255.6)
194 fogrange = 400 / fog_density;
195 fograngerecip = 1.0f / fogrange;
196 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
197 // fog color was already set
203 // FIXME: move this to client?
206 if (gamemode == GAME_NEHAHRA)
208 Cvar_Set("gl_fogenable", "0");
209 Cvar_Set("gl_fogdensity", "0.2");
210 Cvar_Set("gl_fogred", "0.3");
211 Cvar_Set("gl_foggreen", "0.3");
212 Cvar_Set("gl_fogblue", "0.3");
214 fog_density = fog_red = fog_green = fog_blue = 0.0f;
217 // FIXME: move this to client?
218 void FOG_registercvars(void)
223 if (gamemode == GAME_NEHAHRA)
225 Cvar_RegisterVariable (&gl_fogenable);
226 Cvar_RegisterVariable (&gl_fogdensity);
227 Cvar_RegisterVariable (&gl_fogred);
228 Cvar_RegisterVariable (&gl_foggreen);
229 Cvar_RegisterVariable (&gl_fogblue);
230 Cvar_RegisterVariable (&gl_fogstart);
231 Cvar_RegisterVariable (&gl_fogend);
234 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
235 for (x = 0;x < FOGTABLEWIDTH;x++)
237 alpha = exp(r / ((double)x*(double)x));
238 if (x == FOGTABLEWIDTH - 1)
240 fogtable[x] = bound(0, alpha, 1);
244 static void R_BuildBlankTextures(void)
246 unsigned char data[4];
247 data[0] = 128; // normal X
248 data[1] = 128; // normal Y
249 data[2] = 255; // normal Z
250 data[3] = 128; // height
251 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
256 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
261 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
264 static void R_BuildNoTexture(void)
267 unsigned char pix[16][16][4];
268 // this makes a light grey/dark grey checkerboard texture
269 for (y = 0;y < 16;y++)
271 for (x = 0;x < 16;x++)
273 if ((y < 8) ^ (x < 8))
289 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
292 static void R_BuildWhiteCube(void)
294 unsigned char data[6*1*1*4];
295 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
296 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
297 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
298 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
299 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
300 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
301 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
304 static void R_BuildNormalizationCube(void)
308 vec_t s, t, intensity;
310 unsigned char data[6][NORMSIZE][NORMSIZE][4];
311 for (side = 0;side < 6;side++)
313 for (y = 0;y < NORMSIZE;y++)
315 for (x = 0;x < NORMSIZE;x++)
317 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
318 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
353 intensity = 127.0f / sqrt(DotProduct(v, v));
354 data[side][y][x][0] = 128.0f + intensity * v[0];
355 data[side][y][x][1] = 128.0f + intensity * v[1];
356 data[side][y][x][2] = 128.0f + intensity * v[2];
357 data[side][y][x][3] = 255;
361 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
364 static void R_BuildFogTexture(void)
369 unsigned char data1[FOGWIDTH][4];
370 unsigned char data2[FOGWIDTH][4];
371 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
372 for (x = 0;x < FOGWIDTH;x++)
374 alpha = exp(r / ((double)x*(double)x));
375 if (x == FOGWIDTH - 1)
377 b = (int)(256.0 * alpha);
378 b = bound(0, b, 255);
379 data1[x][0] = 255 - b;
380 data1[x][1] = 255 - b;
381 data1[x][2] = 255 - b;
388 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
389 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
392 void gl_main_start(void)
394 r_main_texturepool = R_AllocTexturePool();
395 r_bloom_texture_screen = NULL;
396 r_bloom_texture_bloom = NULL;
397 R_BuildBlankTextures();
399 if (gl_texturecubemap)
402 R_BuildNormalizationCube();
407 void gl_main_shutdown(void)
409 R_FreeTexturePool(&r_main_texturepool);
410 r_bloom_texture_screen = NULL;
411 r_bloom_texture_bloom = NULL;
412 r_texture_blanknormalmap = NULL;
413 r_texture_white = NULL;
414 r_texture_black = NULL;
415 r_texture_whitecube = NULL;
416 r_texture_normalizationcube = NULL;
419 extern void CL_ParseEntityLump(char *entitystring);
420 void gl_main_newmap(void)
422 // FIXME: move this code to client
424 char *entities, entname[MAX_QPATH];
428 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
429 l = (int)strlen(entname) - 4;
430 if (l >= 0 && !strcmp(entname + l, ".bsp"))
432 strcpy(entname + l, ".ent");
433 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
435 CL_ParseEntityLump(entities);
440 if (cl.worldmodel->brush.entities)
441 CL_ParseEntityLump(cl.worldmodel->brush.entities);
445 void GL_Main_Init(void)
447 Matrix4x4_CreateIdentity(&r_identitymatrix);
448 // FIXME: move this to client?
450 Cvar_RegisterVariable(&r_showtris);
451 Cvar_RegisterVariable(&r_shownormals);
452 Cvar_RegisterVariable(&r_drawentities);
453 Cvar_RegisterVariable(&r_drawviewmodel);
454 Cvar_RegisterVariable(&r_speeds);
455 Cvar_RegisterVariable(&r_fullbrights);
456 Cvar_RegisterVariable(&r_wateralpha);
457 Cvar_RegisterVariable(&r_dynamic);
458 Cvar_RegisterVariable(&r_fullbright);
459 Cvar_RegisterVariable(&r_textureunits);
460 Cvar_RegisterVariable(&r_lerpsprites);
461 Cvar_RegisterVariable(&r_lerpmodels);
462 Cvar_RegisterVariable(&r_waterscroll);
463 Cvar_RegisterVariable(&r_drawcollisionbrushes);
464 Cvar_RegisterVariable(&r_bloom);
465 Cvar_RegisterVariable(&r_bloom_intensity);
466 Cvar_RegisterVariable(&r_bloom_blur);
467 Cvar_RegisterVariable(&r_bloom_resolution);
468 Cvar_RegisterVariable(&r_bloom_power);
469 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
470 Cvar_RegisterVariable(&developer_texturelogging);
471 Cvar_RegisterVariable(&gl_lightmaps);
472 Cvar_RegisterVariable(&r_test);
473 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
474 Cvar_SetValue("r_fullbrights", 0);
475 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
478 static vec3_t r_farclip_origin;
479 static vec3_t r_farclip_direction;
480 static vec_t r_farclip_directiondist;
481 static vec_t r_farclip_meshfarclip;
482 static int r_farclip_directionbit0;
483 static int r_farclip_directionbit1;
484 static int r_farclip_directionbit2;
486 // enlarge farclip to accomodate box
487 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
490 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
491 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
492 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
493 if (r_farclip_meshfarclip < d)
494 r_farclip_meshfarclip = d;
497 // return farclip value
498 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
502 VectorCopy(origin, r_farclip_origin);
503 VectorCopy(direction, r_farclip_direction);
504 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
505 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
506 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
507 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
508 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
510 if (r_refdef.worldmodel)
511 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
512 for (i = 0;i < r_refdef.numentities;i++)
513 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
515 return r_farclip_meshfarclip - r_farclip_directiondist;
518 extern void R_Textures_Init(void);
519 extern void GL_Draw_Init(void);
520 extern void GL_Main_Init(void);
521 extern void R_Shadow_Init(void);
522 extern void R_Sky_Init(void);
523 extern void GL_Surf_Init(void);
524 extern void R_Crosshairs_Init(void);
525 extern void R_Light_Init(void);
526 extern void R_Particles_Init(void);
527 extern void R_Explosion_Init(void);
528 extern void gl_backend_init(void);
529 extern void Sbar_Init(void);
530 extern void R_LightningBeams_Init(void);
531 extern void Mod_RenderInit(void);
533 void Render_Init(void)
549 R_LightningBeams_Init();
558 extern char *ENGINE_EXTENSIONS;
561 VID_CheckExtensions();
563 // LordHavoc: report supported extensions
564 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
566 // clear to black (loading plaque will be seen over this)
567 qglClearColor(0,0,0,1);
568 qglClear(GL_COLOR_BUFFER_BIT);
571 int R_CullBox(const vec3_t mins, const vec3_t maxs)
575 for (i = 0;i < 4;i++)
582 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
586 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
590 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
594 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
598 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
602 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
606 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
610 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
618 //==================================================================================
620 static void R_MarkEntities (void)
623 entity_render_t *ent;
625 if (!r_drawentities.integer)
628 r_refdef.worldentity->visframe = r_framecount;
629 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
630 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
632 // worldmodel can check visibility
633 for (i = 0;i < r_refdef.numentities;i++)
635 ent = r_refdef.entities[i];
636 // some of the renderer still relies on origin...
637 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
638 // some of the renderer still relies on scale...
639 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
640 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_worldleafvisible, ent->mins, ent->maxs)))
642 R_UpdateEntLights(ent);
643 ent->visframe = r_framecount;
649 // no worldmodel or it can't check visibility
650 for (i = 0;i < r_refdef.numentities;i++)
652 ent = r_refdef.entities[i];
653 // some of the renderer still relies on origin...
654 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
655 // some of the renderer still relies on scale...
656 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
657 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
659 R_UpdateEntLights(ent);
660 ent->visframe = r_framecount;
666 // only used if skyrendermasked, and normally returns false
667 int R_DrawBrushModelsSky (void)
670 entity_render_t *ent;
672 if (!r_drawentities.integer)
676 for (i = 0;i < r_refdef.numentities;i++)
678 ent = r_refdef.entities[i];
679 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
681 ent->model->DrawSky(ent);
688 void R_DrawNoModel(entity_render_t *ent);
689 void R_DrawModels(void)
692 entity_render_t *ent;
694 if (!r_drawentities.integer)
697 for (i = 0;i < r_refdef.numentities;i++)
699 ent = r_refdef.entities[i];
700 if (ent->visframe == r_framecount)
702 renderstats.entities++;
703 if (ent->model && ent->model->Draw != NULL)
704 ent->model->Draw(ent);
711 static void R_SetFrustum(void)
713 // break apart the view matrix into vectors for various purposes
714 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
715 VectorNegate(r_viewleft, r_viewright);
718 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
719 frustum[0].normal[1] = 0 - 0;
720 frustum[0].normal[2] = -1 - 0;
721 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
722 frustum[1].normal[1] = 0 + 0;
723 frustum[1].normal[2] = -1 + 0;
724 frustum[2].normal[0] = 0 - 0;
725 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
726 frustum[2].normal[2] = -1 - 0;
727 frustum[3].normal[0] = 0 + 0;
728 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
729 frustum[3].normal[2] = -1 + 0;
734 nudge = 1.0 - 1.0 / (1<<23);
735 frustum[4].normal[0] = 0 - 0;
736 frustum[4].normal[1] = 0 - 0;
737 frustum[4].normal[2] = -1 - -nudge;
738 frustum[4].dist = 0 - -2 * zNear * nudge;
739 frustum[5].normal[0] = 0 + 0;
740 frustum[5].normal[1] = 0 + 0;
741 frustum[5].normal[2] = -1 + -nudge;
742 frustum[5].dist = 0 + -2 * zNear * nudge;
748 frustum[0].normal[0] = m[3] - m[0];
749 frustum[0].normal[1] = m[7] - m[4];
750 frustum[0].normal[2] = m[11] - m[8];
751 frustum[0].dist = m[15] - m[12];
753 frustum[1].normal[0] = m[3] + m[0];
754 frustum[1].normal[1] = m[7] + m[4];
755 frustum[1].normal[2] = m[11] + m[8];
756 frustum[1].dist = m[15] + m[12];
758 frustum[2].normal[0] = m[3] - m[1];
759 frustum[2].normal[1] = m[7] - m[5];
760 frustum[2].normal[2] = m[11] - m[9];
761 frustum[2].dist = m[15] - m[13];
763 frustum[3].normal[0] = m[3] + m[1];
764 frustum[3].normal[1] = m[7] + m[5];
765 frustum[3].normal[2] = m[11] + m[9];
766 frustum[3].dist = m[15] + m[13];
768 frustum[4].normal[0] = m[3] - m[2];
769 frustum[4].normal[1] = m[7] - m[6];
770 frustum[4].normal[2] = m[11] - m[10];
771 frustum[4].dist = m[15] - m[14];
773 frustum[5].normal[0] = m[3] + m[2];
774 frustum[5].normal[1] = m[7] + m[6];
775 frustum[5].normal[2] = m[11] + m[10];
776 frustum[5].dist = m[15] + m[14];
781 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
782 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
783 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
784 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
785 VectorCopy(r_viewforward, frustum[4].normal);
786 VectorNormalize(frustum[0].normal);
787 VectorNormalize(frustum[1].normal);
788 VectorNormalize(frustum[2].normal);
789 VectorNormalize(frustum[3].normal);
790 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
791 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
792 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
793 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
794 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
795 PlaneClassify(&frustum[0]);
796 PlaneClassify(&frustum[1]);
797 PlaneClassify(&frustum[2]);
798 PlaneClassify(&frustum[3]);
799 PlaneClassify(&frustum[4]);
801 // LordHavoc: note to all quake engine coders, Quake had a special case
802 // for 90 degrees which assumed a square view (wrong), so I removed it,
803 // Quake2 has it disabled as well.
805 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
806 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
807 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
808 //PlaneClassify(&frustum[0]);
810 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
811 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
812 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
813 //PlaneClassify(&frustum[1]);
815 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
816 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
817 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
818 //PlaneClassify(&frustum[2]);
820 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
821 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
822 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
823 //PlaneClassify(&frustum[3]);
826 //VectorCopy(r_viewforward, frustum[4].normal);
827 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
828 //PlaneClassify(&frustum[4]);
831 static void R_BlendView(void)
833 int screenwidth, screenheight;
838 // set the (poorly named) screenwidth and screenheight variables to
839 // a power of 2 at least as large as the screen, these will define the
840 // size of the texture to allocate
841 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
842 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
844 doblend = r_refdef.viewblend[3] >= 0.01f;
845 dobloom = r_bloom.integer && screenwidth <= gl_max_texture_size && screenheight <= gl_max_texture_size && r_bloom_resolution.value >= 32 && r_bloom_power.integer >= 1 && r_bloom_power.integer < 100 && r_bloom_blur.value >= 0 && r_bloom_blur.value < 512;
847 if (!dobloom && !doblend)
850 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
853 R_Mesh_Matrix(&r_identitymatrix);
854 // vertex coordinates for a quad that covers the screen exactly
855 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
856 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
857 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
858 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
861 int bloomwidth, bloomheight, x, dobloomblend, range;
862 float xoffset, yoffset, r;
864 // allocate textures as needed
865 if (!r_bloom_texture_screen)
866 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
867 if (!r_bloom_texture_bloom)
868 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
869 // set bloomwidth and bloomheight to the bloom resolution that will be
870 // used (often less than the screen resolution for faster rendering)
871 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
872 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
873 // set up a texcoord array for the full resolution screen image
874 // (we have to keep this around to copy back during final render)
875 varray_texcoord2f[0][0] = 0;
876 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
877 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
878 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
879 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
880 varray_texcoord2f[0][5] = 0;
881 varray_texcoord2f[0][6] = 0;
882 varray_texcoord2f[0][7] = 0;
883 // set up a texcoord array for the reduced resolution bloom image
884 // (which will be additive blended over the screen image)
885 varray_texcoord2f[1][0] = 0;
886 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
887 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
888 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
889 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
890 varray_texcoord2f[1][5] = 0;
891 varray_texcoord2f[1][6] = 0;
892 varray_texcoord2f[1][7] = 0;
893 memset(&m, 0, sizeof(m));
894 m.pointer_vertex = varray_vertex3f;
895 m.pointer_texcoord[0] = varray_texcoord2f[0];
896 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
898 // copy view into the full resolution screen image texture
900 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
901 renderstats.bloom_copypixels += r_view_width * r_view_height;
902 // now scale it down to the bloom size and raise to a power of itself
903 // to darken it (this leaves the really bright stuff bright, and
904 // everything else becomes very dark)
905 // TODO: optimize with multitexture or GLSL
906 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
907 GL_BlendFunc(GL_ONE, GL_ZERO);
908 GL_Color(1, 1, 1, 1);
909 R_Mesh_Draw(0, 4, 2, polygonelements);
910 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
911 // render multiple times with a multiply blendfunc to raise to a power
912 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
913 for (x = 1;x < r_bloom_power.integer;x++)
915 R_Mesh_Draw(0, 4, 2, polygonelements);
916 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
918 // we now have a darkened bloom image in the framebuffer, copy it into
919 // the bloom image texture for more processing
920 memset(&m, 0, sizeof(m));
921 m.pointer_vertex = varray_vertex3f;
922 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
923 m.pointer_texcoord[0] = varray_texcoord2f[2];
926 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
927 renderstats.bloom_copypixels += bloomwidth * bloomheight;
928 // blend on at multiple vertical offsets to achieve a vertical blur
929 // TODO: do offset blends using GLSL
930 range = r_bloom_blur.integer * bloomwidth / 320;
931 GL_BlendFunc(GL_ONE, GL_ZERO);
932 for (x = -range;x <= range;x++)
934 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
935 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
936 // compute a texcoord array with the specified x and y offset
937 varray_texcoord2f[2][0] = xoffset+0;
938 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
939 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
940 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
941 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
942 varray_texcoord2f[2][5] = yoffset+0;
943 varray_texcoord2f[2][6] = xoffset+0;
944 varray_texcoord2f[2][7] = yoffset+0;
945 // this r value looks like a 'dot' particle, fading sharply to
946 // black at the edges
947 // (probably not realistic but looks good enough)
948 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
951 GL_Color(r, r, r, 1);
952 R_Mesh_Draw(0, 4, 2, polygonelements);
953 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
954 GL_BlendFunc(GL_ONE, GL_ONE);
956 // copy the vertically blurred bloom view to a texture
958 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
959 renderstats.bloom_copypixels += bloomwidth * bloomheight;
960 // blend the vertically blurred image at multiple offsets horizontally
961 // to finish the blur effect
962 // TODO: do offset blends using GLSL
963 range = r_bloom_blur.integer * bloomwidth / 320;
964 GL_BlendFunc(GL_ONE, GL_ZERO);
965 for (x = -range;x <= range;x++)
967 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
968 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
969 // compute a texcoord array with the specified x and y offset
970 varray_texcoord2f[2][0] = xoffset+0;
971 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
972 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
973 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
974 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
975 varray_texcoord2f[2][5] = yoffset+0;
976 varray_texcoord2f[2][6] = xoffset+0;
977 varray_texcoord2f[2][7] = yoffset+0;
978 // this r value looks like a 'dot' particle, fading sharply to
979 // black at the edges
980 // (probably not realistic but looks good enough)
981 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
984 GL_Color(r, r, r, 1);
985 R_Mesh_Draw(0, 4, 2, polygonelements);
986 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
987 GL_BlendFunc(GL_ONE, GL_ONE);
989 // copy the blurred bloom view to a texture
991 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
992 renderstats.bloom_copypixels += bloomwidth * bloomheight;
993 // go back to full view area
994 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
995 // put the original screen image back in place and blend the bloom
997 memset(&m, 0, sizeof(m));
998 m.pointer_vertex = varray_vertex3f;
999 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1000 m.pointer_texcoord[0] = varray_texcoord2f[0];
1002 dobloomblend = false;
1004 // do both in one pass if possible
1005 if (r_textureunits.integer >= 2 && gl_combine.integer)
1007 dobloomblend = false;
1008 m.texcombinergb[1] = GL_ADD;
1009 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1010 m.pointer_texcoord[1] = varray_texcoord2f[1];
1013 dobloomblend = true;
1016 GL_BlendFunc(GL_ONE, GL_ZERO);
1018 R_Mesh_Draw(0, 4, 2, polygonelements);
1019 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1020 // now blend on the bloom texture if multipass
1023 memset(&m, 0, sizeof(m));
1024 m.pointer_vertex = varray_vertex3f;
1025 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1026 m.pointer_texcoord[0] = varray_texcoord2f[1];
1028 GL_BlendFunc(GL_ONE, GL_ONE);
1030 R_Mesh_Draw(0, 4, 2, polygonelements);
1031 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1036 // apply a color tint to the whole view
1037 memset(&m, 0, sizeof(m));
1038 m.pointer_vertex = varray_vertex3f;
1040 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1041 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1042 R_Mesh_Draw(0, 4, 2, polygonelements);
1046 void R_RenderScene(void);
1048 matrix4x4_t r_waterscrollmatrix;
1055 void R_RenderView(void)
1057 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1058 return; //Host_Error ("R_RenderView: NULL worldmodel");
1060 r_view_width = bound(0, r_refdef.width, vid.width);
1061 r_view_height = bound(0, r_refdef.height, vid.height);
1063 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1064 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1066 r_view_matrix = r_refdef.viewentitymatrix;
1067 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1068 r_rtworld = r_shadow_realtime_world.integer;
1069 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1070 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1071 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1072 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1074 // GL is weird because it's bottom to top, r_view_y is top to bottom
1075 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1076 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1077 GL_ScissorTest(true);
1082 R_TimeReport("setup");
1084 qglDepthFunc(GL_LEQUAL);
1085 qglPolygonOffset(0, 0);
1086 qglEnable(GL_POLYGON_OFFSET_FILL);
1090 qglPolygonOffset(0, 0);
1091 qglDisable(GL_POLYGON_OFFSET_FILL);
1094 R_TimeReport("blendview");
1096 GL_Scissor(0, 0, vid.width, vid.height);
1097 GL_ScissorTest(false);
1100 extern void R_DrawLightningBeams (void);
1101 void R_RenderScene(void)
1103 // don't let sound skip if going slow
1104 if (r_refdef.extraupdate)
1109 R_MeshQueue_BeginScene();
1111 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1115 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1116 if (r_rtworldshadows || r_rtdlightshadows)
1117 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f);
1119 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f, r_farclip);
1121 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1123 Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
1127 R_WorldVisibility();
1128 R_TimeReport("worldvis");
1131 R_TimeReport("markentity");
1133 R_Shadow_UpdateWorldLightSelection();
1135 // don't let sound skip if going slow
1136 if (r_refdef.extraupdate)
1139 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1140 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1142 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1143 R_TimeReport("worldsky");
1146 if (R_DrawBrushModelsSky())
1147 R_TimeReport("bmodelsky");
1149 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1150 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1152 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1153 R_TimeReport("world");
1156 // don't let sound skip if going slow
1157 if (r_refdef.extraupdate)
1160 GL_ShowTrisColor(0, 0.015, 0, 1);
1163 R_TimeReport("models");
1165 // don't let sound skip if going slow
1166 if (r_refdef.extraupdate)
1169 GL_ShowTrisColor(0, 0, 0.033, 1);
1170 R_ShadowVolumeLighting(false);
1171 R_TimeReport("rtlights");
1173 // don't let sound skip if going slow
1174 if (r_refdef.extraupdate)
1177 GL_ShowTrisColor(0.1, 0, 0, 1);
1179 R_DrawLightningBeams();
1180 R_TimeReport("lightning");
1183 R_TimeReport("particles");
1186 R_TimeReport("explosions");
1188 R_MeshQueue_RenderTransparent();
1189 R_TimeReport("drawtrans");
1192 R_TimeReport("coronas");
1194 R_DrawWorldCrosshair();
1195 R_TimeReport("crosshair");
1197 R_MeshQueue_Render();
1198 R_MeshQueue_EndScene();
1200 if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1202 R_ShadowVolumeLighting(true);
1203 R_TimeReport("visiblevolume");
1206 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1208 // don't let sound skip if going slow
1209 if (r_refdef.extraupdate)
1214 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1217 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1219 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1220 GL_DepthMask(false);
1222 R_Mesh_Matrix(&r_identitymatrix);
1224 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1225 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1226 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1227 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1228 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1229 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1230 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1231 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1232 R_FillColors(color, 8, cr, cg, cb, ca);
1235 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1237 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1239 c[0] = c[0] * f1 + fogcolor[0] * f2;
1240 c[1] = c[1] * f1 + fogcolor[1] * f2;
1241 c[2] = c[2] * f1 + fogcolor[2] * f2;
1244 memset(&m, 0, sizeof(m));
1245 m.pointer_vertex = vertex3f;
1246 m.pointer_color = color;
1252 int nomodelelements[24] =
1264 float nomodelvertex3f[6*3] =
1274 float nomodelcolor4f[6*4] =
1276 0.0f, 0.0f, 0.5f, 1.0f,
1277 0.0f, 0.0f, 0.5f, 1.0f,
1278 0.0f, 0.5f, 0.0f, 1.0f,
1279 0.0f, 0.5f, 0.0f, 1.0f,
1280 0.5f, 0.0f, 0.0f, 1.0f,
1281 0.5f, 0.0f, 0.0f, 1.0f
1284 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1286 const entity_render_t *ent = (entity_render_t *)calldata1;
1291 R_Mesh_Matrix(&ent->matrix);
1293 memset(&m, 0, sizeof(m));
1294 m.pointer_vertex = nomodelvertex3f;
1296 if (ent->flags & EF_ADDITIVE)
1298 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1299 GL_DepthMask(false);
1301 else if (ent->alpha < 1)
1303 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1304 GL_DepthMask(false);
1308 GL_BlendFunc(GL_ONE, GL_ZERO);
1311 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1314 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1315 m.pointer_color = color4f;
1316 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1318 for (i = 0, c = color4f;i < 6;i++, c += 4)
1320 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1321 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1322 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1326 else if (ent->alpha != 1)
1328 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1329 m.pointer_color = color4f;
1330 for (i = 0, c = color4f;i < 6;i++, c += 4)
1334 m.pointer_color = nomodelcolor4f;
1336 R_Mesh_Draw(0, 6, 8, nomodelelements);
1339 void R_DrawNoModel(entity_render_t *ent)
1341 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1342 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1344 // R_DrawNoModelCallback(ent, 0);
1347 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1349 vec3_t right1, right2, diff, normal;
1351 VectorSubtract (org2, org1, normal);
1353 // calculate 'right' vector for start
1354 VectorSubtract (r_vieworigin, org1, diff);
1355 CrossProduct (normal, diff, right1);
1356 VectorNormalize (right1);
1358 // calculate 'right' vector for end
1359 VectorSubtract (r_vieworigin, org2, diff);
1360 CrossProduct (normal, diff, right2);
1361 VectorNormalize (right2);
1363 vert[ 0] = org1[0] + width * right1[0];
1364 vert[ 1] = org1[1] + width * right1[1];
1365 vert[ 2] = org1[2] + width * right1[2];
1366 vert[ 3] = org1[0] - width * right1[0];
1367 vert[ 4] = org1[1] - width * right1[1];
1368 vert[ 5] = org1[2] - width * right1[2];
1369 vert[ 6] = org2[0] - width * right2[0];
1370 vert[ 7] = org2[1] - width * right2[1];
1371 vert[ 8] = org2[2] - width * right2[2];
1372 vert[ 9] = org2[0] + width * right2[0];
1373 vert[10] = org2[1] + width * right2[1];
1374 vert[11] = org2[2] + width * right2[2];
1377 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1379 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, int depthdisable, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca)
1381 float fog = 0.0f, ifog;
1385 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1388 R_Mesh_Matrix(&r_identitymatrix);
1389 GL_BlendFunc(blendfunc1, blendfunc2);
1390 GL_DepthMask(false);
1391 GL_DepthTest(!depthdisable);
1393 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1394 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1395 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1396 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1397 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1398 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1399 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1400 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1401 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1402 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1403 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1404 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1406 memset(&m, 0, sizeof(m));
1407 m.tex[0] = R_GetTexture(texture);
1408 m.pointer_texcoord[0] = spritetexcoord2f;
1409 m.pointer_vertex = varray_vertex3f;
1411 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
1412 R_Mesh_Draw(0, 4, 2, polygonelements);
1414 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
1416 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
1417 GL_BlendFunc(blendfunc1, GL_ONE);
1418 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
1419 R_Mesh_Draw(0, 4, 2, polygonelements);
1423 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1427 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1428 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1430 if (i == mesh->numvertices)
1432 if (mesh->numvertices < mesh->maxvertices)
1434 VectorCopy(v, vertex3f);
1435 mesh->numvertices++;
1437 return mesh->numvertices;
1443 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1447 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1448 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1449 e = mesh->element3i + mesh->numtriangles * 3;
1450 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1452 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1453 if (mesh->numtriangles < mesh->maxtriangles)
1458 mesh->numtriangles++;
1460 element[1] = element[2];
1464 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1466 int planenum, planenum2;
1469 mplane_t *plane, *plane2;
1470 float temppoints[2][256*3];
1471 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1475 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1476 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1478 if (planenum2 == planenum)
1480 PolygonF_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, 1.0/32.0, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints);
1483 if (tempnumpoints < 3)
1485 // generate elements forming a triangle fan for this polygon
1486 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1490 void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, matrix4x4_t *matrix, float r, float g, float b, float a)
1492 texturelayer_t *layer;
1493 layer = t->currentlayers + t->currentnumlayers++;
1495 layer->depthmask = depthmask;
1496 layer->blendfunc1 = blendfunc1;
1497 layer->blendfunc2 = blendfunc2;
1498 layer->texture = texture;
1499 layer->texmatrix = *matrix;
1500 layer->color[0] = r;
1501 layer->color[1] = g;
1502 layer->color[2] = b;
1503 layer->color[3] = a;
1506 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1508 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1509 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1513 texture_t *texture = t;
1514 model_t *model = ent->model;
1515 int s = ent->skinnum;
1516 if ((unsigned int)s >= (unsigned int)model->numskins)
1518 if (model->skinscenes)
1520 if (model->skinscenes[s].framecount > 1)
1521 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1523 s = model->skinscenes[s].firstframe;
1526 t = t + s * model->num_surfaces;
1528 t = 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];
1529 texture->currentframe = t;
1532 t->currentmaterialflags = t->basematerialflags;
1533 currentalpha = ent->alpha;
1534 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1535 currentalpha *= r_wateralpha.value;
1536 if (!(ent->flags & RENDER_LIGHT))
1537 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1538 if (ent->effects & EF_ADDITIVE)
1539 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1540 else if (currentalpha < 1)
1541 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1542 if (ent->effects & EF_NODEPTHTEST)
1543 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1544 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1545 t->currenttexmatrix = r_waterscrollmatrix;
1547 t->currenttexmatrix = r_identitymatrix;
1548 t->currentnumlayers = 0;
1549 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1551 if (gl_lightmaps.integer)
1552 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1553 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1555 // transparent sky would be ridiculous
1556 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1557 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1561 int blendfunc1, blendfunc2, depthmask;
1562 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1564 blendfunc1 = GL_SRC_ALPHA;
1565 blendfunc2 = GL_ONE;
1568 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1570 blendfunc1 = GL_SRC_ALPHA;
1571 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1576 blendfunc1 = GL_ONE;
1577 blendfunc2 = GL_ZERO;
1580 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1582 rtexture_t *currentbasetexture;
1584 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1585 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1586 currentbasetexture = (ent->colormap < 0 && t->skin.merged) ? t->skin.merged : t->skin.base;
1587 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1589 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], currentalpha);
1590 if (ent->colormap >= 0 && t->skin.pants)
1591 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2], currentalpha);
1592 if (ent->colormap >= 0 && t->skin.shirt)
1593 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2], currentalpha);
1599 // q3bsp has no lightmap updates, so the lightstylevalue that
1600 // would normally be baked into the lightmaptexture must be
1601 // applied to the color
1602 if (ent->model->type == mod_brushq3)
1603 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1604 // transparent and fullbright are not affected by r_lightmapintensity
1605 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1606 colorscale *= r_lightmapintensity;
1607 if (r_textureunits.integer >= 2 && gl_combine.integer)
1608 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_COMBINE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, currentalpha);
1609 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1610 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale * 0.5f, ent->colormod[1] * colorscale * 0.5f, ent->colormod[2] * colorscale * 0.5f, currentalpha);
1612 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, currentalpha);
1613 if (r_ambient.value >= (1.0f/64.0f))
1614 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), currentalpha);
1615 if (ent->colormap >= 0 && t->skin.pants)
1617 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * colorscale, ent->colormap_pantscolor[1] * colorscale, ent->colormap_pantscolor[2] * colorscale, currentalpha);
1618 if (r_ambient.value >= (1.0f/64.0f))
1619 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * r_ambient.value * (1.0f / 64.0f), currentalpha);
1621 if (ent->colormap >= 0 && t->skin.shirt)
1623 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * colorscale, ent->colormap_shirtcolor[1] * colorscale, ent->colormap_shirtcolor[2] * colorscale, currentalpha);
1624 if (r_ambient.value >= (1.0f/64.0f))
1625 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * r_ambient.value * (1.0f / 64.0f), currentalpha);
1628 if (t->skin.glow != NULL)
1629 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, currentalpha);
1630 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1632 // if this is opaque use alpha blend which will darken the earlier
1635 // if this is an alpha blended material, all the earlier passes
1636 // were darkened by fog already, so we only need to add the fog
1637 // color ontop through the fog mask texture
1639 // if this is an additive blended material, all the earlier passes
1640 // were darkened by fog already, and we should not add fog color
1641 // (because the background was not darkened, there is no fog color
1642 // that was lost behind it).
1643 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], currentalpha);
1650 void R_UpdateAllTextureInfo(entity_render_t *ent)
1654 for (i = 0;i < ent->model->num_textures;i++)
1655 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1658 float *rsurface_vertex3f;
1659 float *rsurface_svector3f;
1660 float *rsurface_tvector3f;
1661 float *rsurface_normal3f;
1662 float *rsurface_lightmapcolor4f;
1664 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1667 float center[3], forward[3], right[3], up[3], v[4][3];
1668 matrix4x4_t matrix1, imatrix1;
1669 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1671 rsurface_vertex3f = varray_vertex3f;
1672 rsurface_svector3f = NULL;
1673 rsurface_tvector3f = NULL;
1674 rsurface_normal3f = NULL;
1675 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1679 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1680 rsurface_svector3f = surface->groupmesh->data_svector3f;
1681 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1682 rsurface_normal3f = surface->groupmesh->data_normal3f;
1684 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1686 if (!rsurface_svector3f)
1688 rsurface_svector3f = varray_svector3f;
1689 rsurface_tvector3f = varray_tvector3f;
1690 rsurface_normal3f = varray_normal3f;
1691 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
1693 // a single autosprite surface can contain multiple sprites...
1694 VectorClear(forward);
1696 VectorSet(up, 0, 0, 1);
1697 for (j = 0;j < surface->num_vertices - 3;j += 4)
1699 VectorClear(center);
1700 for (i = 0;i < 4;i++)
1701 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1702 VectorScale(center, 0.25f, center);
1703 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1704 Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
1705 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1706 for (i = 0;i < 4;i++)
1707 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1708 forward[0] = modelorg[0] - center[0];
1709 forward[1] = modelorg[1] - center[1];
1710 VectorNormalize(forward);
1711 right[0] = forward[1];
1712 right[1] = -forward[0];
1713 for (i = 0;i < 4;i++)
1714 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1716 rsurface_vertex3f = varray_vertex3f;
1717 rsurface_svector3f = NULL;
1718 rsurface_tvector3f = NULL;
1719 rsurface_normal3f = NULL;
1721 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1723 if (!rsurface_svector3f)
1725 rsurface_svector3f = varray_svector3f;
1726 rsurface_tvector3f = varray_tvector3f;
1727 rsurface_normal3f = varray_normal3f;
1728 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
1730 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1731 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1732 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1733 // a single autosprite surface can contain multiple sprites...
1734 for (j = 0;j < surface->num_vertices - 3;j += 4)
1736 VectorClear(center);
1737 for (i = 0;i < 4;i++)
1738 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1739 VectorScale(center, 0.25f, center);
1740 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1741 Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
1742 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1743 for (i = 0;i < 4;i++)
1744 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1745 for (i = 0;i < 4;i++)
1746 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1748 rsurface_vertex3f = varray_vertex3f;
1749 rsurface_svector3f = NULL;
1750 rsurface_tvector3f = NULL;
1751 rsurface_normal3f = NULL;
1753 R_Mesh_VertexPointer(rsurface_vertex3f);
1756 void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
1764 vec4_t ambientcolor4f;
1765 vec3_t diffusecolor;
1766 vec3_t diffusenormal;
1767 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1769 rsurface_lightmapcolor4f = varray_color4f;
1770 if (rsurface_normal3f == NULL)
1772 rsurface_normal3f = varray_normal3f;
1773 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
1775 R_LightModel_CalcVertexColors(ambientcolor4f, diffusecolor, diffusenormal, surface->groupmesh->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, rsurface_lightmapcolor4f + 4 * surface->num_firstvertex);
1784 r = ambientcolor4f[0];
1785 g = ambientcolor4f[1];
1786 b = ambientcolor4f[2];
1787 a = ambientcolor4f[3];
1788 rsurface_lightmapcolor4f = NULL;
1791 else if (lightmode >= 1)
1793 if (surface->lightmapinfo)
1795 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1797 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1800 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1801 VectorScale(lm, scale, c);
1802 if (surface->lightmapinfo->styles[1] != 255)
1804 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1806 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1807 VectorMA(c, scale, lm, c);
1808 if (surface->lightmapinfo->styles[2] != 255)
1811 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1812 VectorMA(c, scale, lm, c);
1813 if (surface->lightmapinfo->styles[3] != 255)
1816 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1817 VectorMA(c, scale, lm, c);
1825 rsurface_lightmapcolor4f = varray_color4f;
1828 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1831 rsurface_lightmapcolor4f = NULL;
1834 if (rsurface_lightmapcolor4f)
1836 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
1838 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1847 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
1849 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1856 rsurface_lightmapcolor4f = varray_color4f;
1858 if (applycolor && rsurface_lightmapcolor4f)
1860 for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
1867 rsurface_lightmapcolor4f = varray_color4f;
1869 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1870 GL_Color(r, g, b, a);
1873 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1875 int texturesurfaceindex;
1877 const msurface_t *surface;
1878 qboolean applycolor;
1880 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1882 renderstats.entities_surfaces += texturenumsurfaces;
1883 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1884 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1885 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1886 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1887 qglDisable(GL_CULL_FACE);
1888 if (texture->currentnumlayers)
1891 texturelayer_t *layer;
1892 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1895 int layertexrgbscale;
1896 GL_DepthMask(layer->depthmask);
1897 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1898 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1900 layertexrgbscale = 4;
1901 VectorScale(layer->color, 0.25f, layercolor);
1903 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
1905 layertexrgbscale = 2;
1906 VectorScale(layer->color, 0.5f, layercolor);
1910 layertexrgbscale = 1;
1911 VectorScale(layer->color, 1.0f, layercolor);
1913 layercolor[3] = layer->color[3];
1914 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1915 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
1916 switch (layer->type)
1918 case TEXTURELAYERTYPE_SKY:
1921 skyrendernow = false;
1922 if (skyrendermasked)
1925 // restore entity matrix and GL_Color
1926 R_Mesh_Matrix(&ent->matrix);
1927 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1930 // LordHavoc: HalfLife maps have freaky skypolys...
1931 //if (!ent->model->brush.ishlbsp)
1933 if (skyrendermasked)
1935 // depth-only (masking)
1936 GL_ColorMask(0,0,0,0);
1937 // just to make sure that braindead drivers don't draw anything
1938 // despite that colormask...
1939 GL_BlendFunc(GL_ZERO, GL_ONE);
1944 GL_BlendFunc(GL_ONE, GL_ZERO);
1946 memset(&m, 0, sizeof(m));
1948 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1950 surface = texturesurfacelist[texturesurfaceindex];
1951 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1952 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1953 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1954 GL_LockArrays(0, 0);
1956 if (skyrendermasked)
1957 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1960 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
1961 memset(&m, 0, sizeof(m));
1962 m.tex[1] = R_GetTexture(layer->texture);
1963 m.texmatrix[1] = layer->texmatrix;
1964 m.texrgbscale[1] = layertexrgbscale;
1965 m.pointer_color = varray_color4f;
1967 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1969 surface = texturesurfacelist[texturesurfaceindex];
1970 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1971 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1972 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1975 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1976 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1978 else if (surface->lightmaptexture)
1980 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1981 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1985 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1986 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1988 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1989 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1990 GL_LockArrays(0, 0);
1993 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
1994 memset(&m, 0, sizeof(m));
1995 m.tex[0] = R_GetTexture(layer->texture);
1996 m.texmatrix[0] = layer->texmatrix;
1997 m.pointer_color = varray_color4f;
1998 m.texrgbscale[0] = layertexrgbscale;
2000 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2002 surface = texturesurfacelist[texturesurfaceindex];
2003 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2004 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2007 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2008 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2010 else if (surface->lightmaptexture)
2012 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2013 R_Mesh_ColorPointer(NULL);
2017 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2018 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2020 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2021 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2022 GL_LockArrays(0, 0);
2024 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2025 memset(&m, 0, sizeof(m));
2026 m.tex[0] = R_GetTexture(layer->texture);
2027 m.texmatrix[0] = layer->texmatrix;
2028 m.pointer_color = varray_color4f;
2029 m.texrgbscale[0] = layertexrgbscale;
2031 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2033 surface = texturesurfacelist[texturesurfaceindex];
2034 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2035 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2036 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2037 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2038 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2039 GL_LockArrays(0, 0);
2042 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2043 memset(&m, 0, sizeof(m));
2044 m.tex[0] = R_GetTexture(layer->texture);
2045 m.texmatrix[0] = layer->texmatrix;
2046 m.texrgbscale[0] = layertexrgbscale;
2047 m.pointer_color = varray_color4f;
2049 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2051 surface = texturesurfacelist[texturesurfaceindex];
2052 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2053 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2054 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2055 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2056 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2057 GL_LockArrays(0, 0);
2060 case TEXTURELAYERTYPE_TEXTURE:
2061 memset(&m, 0, sizeof(m));
2062 m.tex[0] = R_GetTexture(layer->texture);
2063 m.texmatrix[0] = layer->texmatrix;
2064 m.pointer_color = varray_color4f;
2065 m.texrgbscale[0] = layertexrgbscale;
2067 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2069 surface = texturesurfacelist[texturesurfaceindex];
2070 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2071 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2072 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2073 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2074 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2075 GL_LockArrays(0, 0);
2078 case TEXTURELAYERTYPE_FOG:
2079 memset(&m, 0, sizeof(m));
2082 m.tex[0] = R_GetTexture(layer->texture);
2083 m.texmatrix[0] = layer->texmatrix;
2086 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2090 surface = texturesurfacelist[texturesurfaceindex];
2091 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2093 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2094 R_Mesh_ColorPointer(varray_color4f);
2095 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2097 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2098 c[0] = layercolor[0];
2099 c[1] = layercolor[1];
2100 c[2] = layercolor[2];
2101 c[3] = f * layercolor[3];
2103 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2104 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2105 GL_LockArrays(0, 0);
2109 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2111 // if trying to do overbright on first pass of an opaque surface
2112 // when combine is not supported, brighten as a post process
2113 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2116 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2117 GL_Color(1, 1, 1, 1);
2118 memset(&m, 0, sizeof(m));
2120 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2122 surface = texturesurfacelist[texturesurfaceindex];
2123 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2124 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2125 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2126 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2127 GL_LockArrays(0, 0);
2131 if (r_shownormals.integer && !r_showtrispass)
2136 GL_DepthMask(texture->currentlayers->depthmask);
2137 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
2138 memset(&m, 0, sizeof(m));
2140 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2142 surface = texturesurfacelist[texturesurfaceindex];
2143 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2144 if (!rsurface_svector3f)
2146 rsurface_svector3f = varray_svector3f;
2147 rsurface_tvector3f = varray_tvector3f;
2148 rsurface_normal3f = varray_normal3f;
2149 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
2151 GL_Color(1, 0, 0, 1);
2153 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2155 VectorCopy(rsurface_vertex3f + k * 3, v);
2156 qglVertex3f(v[0], v[1], v[2]);
2157 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
2158 qglVertex3f(v[0], v[1], v[2]);
2160 GL_Color(0, 0, 1, 1);
2161 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2163 VectorCopy(rsurface_vertex3f + k * 3, v);
2164 qglVertex3f(v[0], v[1], v[2]);
2165 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
2166 qglVertex3f(v[0], v[1], v[2]);
2168 GL_Color(0, 1, 0, 1);
2169 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2171 VectorCopy(rsurface_vertex3f + k * 3, v);
2172 qglVertex3f(v[0], v[1], v[2]);
2173 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
2174 qglVertex3f(v[0], v[1], v[2]);
2180 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2181 qglEnable(GL_CULL_FACE);
2184 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2186 const entity_render_t *ent = (entity_render_t *)calldata1;
2187 const msurface_t *surface = ent->model->data_surfaces + calldata2;
2191 texture = surface->texture;
2192 if (texture->basematerialflags & MATERIALFLAG_SKY)
2193 return; // transparent sky is too difficult
2194 R_UpdateTextureInfo(ent, texture);
2196 R_Mesh_Matrix(&ent->matrix);
2197 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2198 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2201 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2203 int texturesurfaceindex;
2204 const msurface_t *surface;
2205 vec3_t tempcenter, center;
2206 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2208 // drawing sky transparently would be too difficult
2209 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2211 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2213 surface = texturesurfacelist[texturesurfaceindex];
2214 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2215 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2216 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2217 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2218 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2223 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2226 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2227 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2229 int i, j, f, flagsmask;
2230 int counttriangles = 0;
2231 msurface_t *surface, **surfacechain;
2232 texture_t *t, *texture;
2233 model_t *model = ent->model;
2235 const int maxsurfacelist = 1024;
2236 int numsurfacelist = 0;
2237 const msurface_t *surfacelist[1024];
2240 R_Mesh_Matrix(&ent->matrix);
2241 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2243 // update light styles
2244 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2246 for (i = 0;i < model->brushq1.light_styles;i++)
2248 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2250 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2251 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2252 for (;(surface = *surfacechain);surfacechain++)
2253 surface->cached_dlight = true;
2258 R_UpdateAllTextureInfo(ent);
2259 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2264 if (ent == r_refdef.worldentity)
2266 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2268 if (!r_worldsurfacevisible[j])
2270 if (t != surface->texture)
2274 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2277 t = surface->texture;
2278 texture = t->currentframe;
2279 f = texture->currentmaterialflags & flagsmask;
2281 if (f && surface->num_triangles)
2283 // if lightmap parameters changed, rebuild lightmap texture
2284 if (surface->cached_dlight && surface->lightmapinfo->samples)
2285 R_BuildLightMap(ent, surface);
2286 // add face to draw list
2287 surfacelist[numsurfacelist++] = surface;
2288 counttriangles += surface->num_triangles;
2289 if (numsurfacelist >= maxsurfacelist)
2291 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2299 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2301 if (t != surface->texture)
2305 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2308 t = surface->texture;
2309 texture = t->currentframe;
2310 f = texture->currentmaterialflags & flagsmask;
2312 if (f && surface->num_triangles)
2314 // if lightmap parameters changed, rebuild lightmap texture
2315 if (surface->cached_dlight && surface->lightmapinfo->samples)
2316 R_BuildLightMap(ent, surface);
2317 // add face to draw list
2318 surfacelist[numsurfacelist++] = surface;
2319 counttriangles += surface->num_triangles;
2320 if (numsurfacelist >= maxsurfacelist)
2322 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2329 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2330 if (!r_showtrispass)
2331 renderstats.entities_triangles += counttriangles;