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_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
1290 R_Mesh_Matrix(&ent->matrix);
1292 memset(&m, 0, sizeof(m));
1293 m.pointer_vertex = nomodelvertex3f;
1295 if (ent->flags & EF_ADDITIVE)
1297 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1298 GL_DepthMask(false);
1300 else if (ent->alpha < 1)
1302 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1303 GL_DepthMask(false);
1307 GL_BlendFunc(GL_ONE, GL_ZERO);
1310 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1313 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1314 m.pointer_color = color4f;
1315 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1317 for (i = 0, c = color4f;i < 6;i++, c += 4)
1319 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1320 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1321 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1325 else if (ent->alpha != 1)
1327 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1328 m.pointer_color = color4f;
1329 for (i = 0, c = color4f;i < 6;i++, c += 4)
1333 m.pointer_color = nomodelcolor4f;
1335 R_Mesh_Draw(0, 6, 8, nomodelelements);
1338 void R_DrawNoModel(entity_render_t *ent)
1340 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1341 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1343 // R_DrawNoModelCallback(ent, 0);
1346 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1348 vec3_t right1, right2, diff, normal;
1350 VectorSubtract (org2, org1, normal);
1352 // calculate 'right' vector for start
1353 VectorSubtract (r_vieworigin, org1, diff);
1354 CrossProduct (normal, diff, right1);
1355 VectorNormalize (right1);
1357 // calculate 'right' vector for end
1358 VectorSubtract (r_vieworigin, org2, diff);
1359 CrossProduct (normal, diff, right2);
1360 VectorNormalize (right2);
1362 vert[ 0] = org1[0] + width * right1[0];
1363 vert[ 1] = org1[1] + width * right1[1];
1364 vert[ 2] = org1[2] + width * right1[2];
1365 vert[ 3] = org1[0] - width * right1[0];
1366 vert[ 4] = org1[1] - width * right1[1];
1367 vert[ 5] = org1[2] - width * right1[2];
1368 vert[ 6] = org2[0] - width * right2[0];
1369 vert[ 7] = org2[1] - width * right2[1];
1370 vert[ 8] = org2[2] - width * right2[2];
1371 vert[ 9] = org2[0] + width * right2[0];
1372 vert[10] = org2[1] + width * right2[1];
1373 vert[11] = org2[2] + width * right2[2];
1376 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1378 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)
1380 float fog = 0.0f, ifog;
1384 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1387 R_Mesh_Matrix(&r_identitymatrix);
1388 GL_BlendFunc(blendfunc1, blendfunc2);
1389 GL_DepthMask(false);
1390 GL_DepthTest(!depthdisable);
1392 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1393 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1394 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1395 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1396 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1397 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1398 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1399 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1400 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1401 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1402 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1403 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1405 memset(&m, 0, sizeof(m));
1406 m.tex[0] = R_GetTexture(texture);
1407 m.pointer_texcoord[0] = spritetexcoord2f;
1408 m.pointer_vertex = varray_vertex3f;
1410 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
1411 R_Mesh_Draw(0, 4, 2, polygonelements);
1413 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
1415 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
1416 GL_BlendFunc(blendfunc1, GL_ONE);
1417 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
1418 R_Mesh_Draw(0, 4, 2, polygonelements);
1422 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1426 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1427 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1429 if (i == mesh->numvertices)
1431 if (mesh->numvertices < mesh->maxvertices)
1433 VectorCopy(v, vertex3f);
1434 mesh->numvertices++;
1436 return mesh->numvertices;
1442 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1446 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1447 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1448 e = mesh->element3i + mesh->numtriangles * 3;
1449 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1451 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1452 if (mesh->numtriangles < mesh->maxtriangles)
1457 mesh->numtriangles++;
1459 element[1] = element[2];
1463 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1465 int planenum, planenum2;
1468 mplane_t *plane, *plane2;
1469 float temppoints[2][256*3];
1470 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1474 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1475 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1477 if (planenum2 == planenum)
1479 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);
1482 if (tempnumpoints < 3)
1484 // generate elements forming a triangle fan for this polygon
1485 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1489 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)
1491 texturelayer_t *layer;
1492 layer = t->currentlayers + t->currentnumlayers++;
1494 layer->depthmask = depthmask;
1495 layer->blendfunc1 = blendfunc1;
1496 layer->blendfunc2 = blendfunc2;
1497 layer->texture = texture;
1498 layer->texmatrix = *matrix;
1499 layer->color[0] = r;
1500 layer->color[1] = g;
1501 layer->color[2] = b;
1502 layer->color[3] = a;
1505 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1507 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1508 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1511 texture_t *texture = t;
1512 model_t *model = ent->model;
1513 int s = ent->skinnum;
1514 if ((unsigned int)s >= (unsigned int)model->numskins)
1516 if (model->skinscenes)
1518 if (model->skinscenes[s].framecount > 1)
1519 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1521 s = model->skinscenes[s].firstframe;
1524 t = t + s * model->num_surfaces;
1526 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];
1527 texture->currentframe = t;
1530 t->currentmaterialflags = t->basematerialflags;
1531 t->currentalpha = ent->alpha;
1532 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1533 t->currentalpha *= r_wateralpha.value;
1534 if (!(ent->flags & RENDER_LIGHT))
1535 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1536 if (ent->effects & EF_ADDITIVE)
1537 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1538 else if (t->currentalpha < 1)
1539 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1540 if (ent->effects & EF_NODEPTHTEST)
1541 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1542 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1543 t->currenttexmatrix = r_waterscrollmatrix;
1545 t->currenttexmatrix = r_identitymatrix;
1546 t->currentnumlayers = 0;
1547 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1549 if (gl_lightmaps.integer)
1550 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1551 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1553 // transparent sky would be ridiculous
1554 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1555 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1559 int blendfunc1, blendfunc2, depthmask;
1560 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1562 blendfunc1 = GL_SRC_ALPHA;
1563 blendfunc2 = GL_ONE;
1566 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1568 blendfunc1 = GL_SRC_ALPHA;
1569 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1574 blendfunc1 = GL_ONE;
1575 blendfunc2 = GL_ZERO;
1578 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1580 rtexture_t *currentbasetexture;
1582 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1583 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1584 currentbasetexture = (ent->colormap < 0 && t->skin.merged) ? t->skin.merged : t->skin.base;
1585 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1587 // fullbright is not affected by r_lightmapintensity
1588 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
1589 if (ent->colormap >= 0 && t->skin.pants)
1590 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], t->currentalpha);
1591 if (ent->colormap >= 0 && t->skin.shirt)
1592 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], t->currentalpha);
1598 // q3bsp has no lightmap updates, so the lightstylevalue that
1599 // would normally be baked into the lightmaptexture must be
1600 // applied to the color
1601 if (ent->model->type == mod_brushq3)
1602 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1603 colorscale *= r_lightmapintensity;
1604 if (r_textureunits.integer >= 2 && gl_combine.integer)
1605 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, t->currentalpha);
1606 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1607 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, t->currentalpha);
1609 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, t->currentalpha);
1610 if (r_ambient.value >= (1.0f/64.0f))
1611 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), t->currentalpha);
1612 if (ent->colormap >= 0 && t->skin.pants)
1614 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, t->currentalpha);
1615 if (r_ambient.value >= (1.0f/64.0f))
1616 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), t->currentalpha);
1618 if (ent->colormap >= 0 && t->skin.shirt)
1620 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, t->currentalpha);
1621 if (r_ambient.value >= (1.0f/64.0f))
1622 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), t->currentalpha);
1625 if (t->skin.glow != NULL)
1626 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
1627 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1629 // if this is opaque use alpha blend which will darken the earlier
1632 // if this is an alpha blended material, all the earlier passes
1633 // were darkened by fog already, so we only need to add the fog
1634 // color ontop through the fog mask texture
1636 // if this is an additive blended material, all the earlier passes
1637 // were darkened by fog already, and we should not add fog color
1638 // (because the background was not darkened, there is no fog color
1639 // that was lost behind it).
1640 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], t->currentalpha);
1647 void R_UpdateAllTextureInfo(entity_render_t *ent)
1651 for (i = 0;i < ent->model->num_textures;i++)
1652 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1655 float *rsurface_vertex3f;
1656 float *rsurface_svector3f;
1657 float *rsurface_tvector3f;
1658 float *rsurface_normal3f;
1659 float *rsurface_lightmapcolor4f;
1661 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1664 float center[3], forward[3], right[3], up[3], v[4][3];
1665 matrix4x4_t matrix1, imatrix1;
1666 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1668 rsurface_vertex3f = varray_vertex3f;
1669 rsurface_svector3f = NULL;
1670 rsurface_tvector3f = NULL;
1671 rsurface_normal3f = NULL;
1672 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1676 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1677 rsurface_svector3f = surface->groupmesh->data_svector3f;
1678 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1679 rsurface_normal3f = surface->groupmesh->data_normal3f;
1681 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1683 if (!rsurface_svector3f)
1685 rsurface_svector3f = varray_svector3f;
1686 rsurface_tvector3f = varray_tvector3f;
1687 rsurface_normal3f = varray_normal3f;
1688 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);
1690 // a single autosprite surface can contain multiple sprites...
1691 VectorClear(forward);
1693 VectorSet(up, 0, 0, 1);
1694 for (j = 0;j < surface->num_vertices - 3;j += 4)
1696 VectorClear(center);
1697 for (i = 0;i < 4;i++)
1698 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1699 VectorScale(center, 0.25f, center);
1700 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1701 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);
1702 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1703 for (i = 0;i < 4;i++)
1704 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1705 forward[0] = modelorg[0] - center[0];
1706 forward[1] = modelorg[1] - center[1];
1707 VectorNormalize(forward);
1708 right[0] = forward[1];
1709 right[1] = -forward[0];
1710 for (i = 0;i < 4;i++)
1711 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1713 rsurface_vertex3f = varray_vertex3f;
1714 rsurface_svector3f = NULL;
1715 rsurface_tvector3f = NULL;
1716 rsurface_normal3f = NULL;
1718 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1720 if (!rsurface_svector3f)
1722 rsurface_svector3f = varray_svector3f;
1723 rsurface_tvector3f = varray_tvector3f;
1724 rsurface_normal3f = varray_normal3f;
1725 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);
1727 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1728 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1729 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1730 // a single autosprite surface can contain multiple sprites...
1731 for (j = 0;j < surface->num_vertices - 3;j += 4)
1733 VectorClear(center);
1734 for (i = 0;i < 4;i++)
1735 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1736 VectorScale(center, 0.25f, center);
1737 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1738 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);
1739 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1740 for (i = 0;i < 4;i++)
1741 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1742 for (i = 0;i < 4;i++)
1743 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1745 rsurface_vertex3f = varray_vertex3f;
1746 rsurface_svector3f = NULL;
1747 rsurface_tvector3f = NULL;
1748 rsurface_normal3f = NULL;
1750 R_Mesh_VertexPointer(rsurface_vertex3f);
1753 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)
1761 vec4_t ambientcolor4f;
1762 vec3_t diffusecolor;
1763 vec3_t diffusenormal;
1764 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1766 rsurface_lightmapcolor4f = varray_color4f;
1767 if (rsurface_normal3f == NULL)
1769 rsurface_normal3f = varray_normal3f;
1770 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);
1772 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);
1781 r = ambientcolor4f[0];
1782 g = ambientcolor4f[1];
1783 b = ambientcolor4f[2];
1784 a = ambientcolor4f[3];
1785 rsurface_lightmapcolor4f = NULL;
1788 else if (lightmode >= 1)
1790 if (surface->lightmapinfo)
1792 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1794 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1797 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1798 VectorScale(lm, scale, c);
1799 if (surface->lightmapinfo->styles[1] != 255)
1801 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1803 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1804 VectorMA(c, scale, lm, c);
1805 if (surface->lightmapinfo->styles[2] != 255)
1808 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1809 VectorMA(c, scale, lm, c);
1810 if (surface->lightmapinfo->styles[3] != 255)
1813 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1814 VectorMA(c, scale, lm, c);
1822 rsurface_lightmapcolor4f = varray_color4f;
1825 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1828 rsurface_lightmapcolor4f = NULL;
1831 if (rsurface_lightmapcolor4f)
1833 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)
1835 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1844 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)
1846 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1853 rsurface_lightmapcolor4f = varray_color4f;
1855 if (applycolor && rsurface_lightmapcolor4f)
1857 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)
1864 rsurface_lightmapcolor4f = varray_color4f;
1866 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1867 GL_Color(r, g, b, a);
1870 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1872 int texturesurfaceindex;
1874 const msurface_t *surface;
1875 qboolean applycolor;
1877 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1879 renderstats.entities_surfaces += texturenumsurfaces;
1880 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1881 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1882 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1883 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
1884 qglDisable(GL_CULL_FACE);
1885 if (texture->currentnumlayers)
1888 texturelayer_t *layer;
1889 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1892 int layertexrgbscale;
1893 GL_DepthMask(layer->depthmask);
1894 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1895 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1897 layertexrgbscale = 4;
1898 VectorScale(layer->color, 0.25f, layercolor);
1900 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
1902 layertexrgbscale = 2;
1903 VectorScale(layer->color, 0.5f, layercolor);
1907 layertexrgbscale = 1;
1908 VectorScale(layer->color, 1.0f, layercolor);
1910 layercolor[3] = layer->color[3];
1911 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1912 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
1913 switch (layer->type)
1915 case TEXTURELAYERTYPE_SKY:
1918 skyrendernow = false;
1919 if (skyrendermasked)
1922 // restore entity matrix and GL_Color
1923 R_Mesh_Matrix(&ent->matrix);
1924 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1927 // LordHavoc: HalfLife maps have freaky skypolys...
1928 //if (!ent->model->brush.ishlbsp)
1930 if (skyrendermasked)
1932 // depth-only (masking)
1933 GL_ColorMask(0,0,0,0);
1934 // just to make sure that braindead drivers don't draw anything
1935 // despite that colormask...
1936 GL_BlendFunc(GL_ZERO, GL_ONE);
1941 GL_BlendFunc(GL_ONE, GL_ZERO);
1943 memset(&m, 0, sizeof(m));
1945 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1947 surface = texturesurfacelist[texturesurfaceindex];
1948 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1949 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1950 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1951 GL_LockArrays(0, 0);
1953 if (skyrendermasked)
1954 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1957 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
1958 memset(&m, 0, sizeof(m));
1959 m.tex[1] = R_GetTexture(layer->texture);
1960 m.texmatrix[1] = layer->texmatrix;
1961 m.texrgbscale[1] = layertexrgbscale;
1962 m.pointer_color = varray_color4f;
1964 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1966 surface = texturesurfacelist[texturesurfaceindex];
1967 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1968 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1969 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1972 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1973 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1975 else if (surface->lightmaptexture)
1977 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1978 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1982 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1983 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1985 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1986 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1987 GL_LockArrays(0, 0);
1990 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
1991 memset(&m, 0, sizeof(m));
1992 m.tex[0] = R_GetTexture(layer->texture);
1993 m.texmatrix[0] = layer->texmatrix;
1994 m.pointer_color = varray_color4f;
1995 m.texrgbscale[0] = layertexrgbscale;
1997 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1999 surface = texturesurfacelist[texturesurfaceindex];
2000 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2001 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2004 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2005 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2007 else if (surface->lightmaptexture)
2009 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2010 R_Mesh_ColorPointer(NULL);
2014 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2015 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2017 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2018 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2019 GL_LockArrays(0, 0);
2021 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2022 memset(&m, 0, sizeof(m));
2023 m.tex[0] = R_GetTexture(layer->texture);
2024 m.texmatrix[0] = layer->texmatrix;
2025 m.pointer_color = varray_color4f;
2026 m.texrgbscale[0] = layertexrgbscale;
2028 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2030 surface = texturesurfacelist[texturesurfaceindex];
2031 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2032 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2033 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2034 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2035 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2036 GL_LockArrays(0, 0);
2039 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2040 memset(&m, 0, sizeof(m));
2041 m.tex[0] = R_GetTexture(layer->texture);
2042 m.texmatrix[0] = layer->texmatrix;
2043 m.texrgbscale[0] = layertexrgbscale;
2044 m.pointer_color = varray_color4f;
2046 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2048 surface = texturesurfacelist[texturesurfaceindex];
2049 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2050 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2051 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2052 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2053 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2054 GL_LockArrays(0, 0);
2057 case TEXTURELAYERTYPE_TEXTURE:
2058 memset(&m, 0, sizeof(m));
2059 m.tex[0] = R_GetTexture(layer->texture);
2060 m.texmatrix[0] = layer->texmatrix;
2061 m.pointer_color = varray_color4f;
2062 m.texrgbscale[0] = layertexrgbscale;
2064 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2066 surface = texturesurfacelist[texturesurfaceindex];
2067 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2068 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2069 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2070 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2071 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2072 GL_LockArrays(0, 0);
2075 case TEXTURELAYERTYPE_FOG:
2076 memset(&m, 0, sizeof(m));
2079 m.tex[0] = R_GetTexture(layer->texture);
2080 m.texmatrix[0] = layer->texmatrix;
2083 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2087 surface = texturesurfacelist[texturesurfaceindex];
2088 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2090 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2091 R_Mesh_ColorPointer(varray_color4f);
2092 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)
2094 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2095 c[0] = layercolor[0];
2096 c[1] = layercolor[1];
2097 c[2] = layercolor[2];
2098 c[3] = f * layercolor[3];
2100 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2101 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2102 GL_LockArrays(0, 0);
2106 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2108 // if trying to do overbright on first pass of an opaque surface
2109 // when combine is not supported, brighten as a post process
2110 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2113 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2114 GL_Color(1, 1, 1, 1);
2115 memset(&m, 0, sizeof(m));
2117 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2119 surface = texturesurfacelist[texturesurfaceindex];
2120 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2121 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2122 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2123 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2124 GL_LockArrays(0, 0);
2128 if (r_shownormals.integer && !r_showtrispass)
2133 GL_DepthMask(texture->currentlayers->depthmask);
2134 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
2135 memset(&m, 0, sizeof(m));
2137 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2139 surface = texturesurfacelist[texturesurfaceindex];
2140 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2141 if (!rsurface_svector3f)
2143 rsurface_svector3f = varray_svector3f;
2144 rsurface_tvector3f = varray_tvector3f;
2145 rsurface_normal3f = varray_normal3f;
2146 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);
2148 GL_Color(1, 0, 0, 1);
2150 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2152 VectorCopy(rsurface_vertex3f + k * 3, v);
2153 qglVertex3f(v[0], v[1], v[2]);
2154 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
2155 qglVertex3f(v[0], v[1], v[2]);
2157 GL_Color(0, 0, 1, 1);
2158 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2160 VectorCopy(rsurface_vertex3f + k * 3, v);
2161 qglVertex3f(v[0], v[1], v[2]);
2162 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
2163 qglVertex3f(v[0], v[1], v[2]);
2165 GL_Color(0, 1, 0, 1);
2166 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2168 VectorCopy(rsurface_vertex3f + k * 3, v);
2169 qglVertex3f(v[0], v[1], v[2]);
2170 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
2171 qglVertex3f(v[0], v[1], v[2]);
2177 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2178 qglEnable(GL_CULL_FACE);
2181 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2183 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
2187 texture = surface->texture;
2188 if (texture->basematerialflags & MATERIALFLAG_SKY)
2189 return; // transparent sky is too difficult
2190 R_UpdateTextureInfo(ent, texture);
2192 R_Mesh_Matrix(&ent->matrix);
2193 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2194 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2197 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2199 int texturesurfaceindex;
2200 const msurface_t *surface;
2201 vec3_t tempcenter, center;
2202 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2204 // drawing sky transparently would be too difficult
2205 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2207 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2209 surface = texturesurfacelist[texturesurfaceindex];
2210 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2211 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2212 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2213 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2214 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
2219 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2222 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2223 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2225 int i, j, f, flagsmask;
2226 int counttriangles = 0;
2227 msurface_t *surface, **surfacechain;
2228 texture_t *t, *texture;
2229 model_t *model = ent->model;
2231 const int maxsurfacelist = 1024;
2232 int numsurfacelist = 0;
2233 const msurface_t *surfacelist[1024];
2236 R_Mesh_Matrix(&ent->matrix);
2237 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2239 // update light styles
2240 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2242 for (i = 0;i < model->brushq1.light_styles;i++)
2244 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2246 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2247 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2248 for (;(surface = *surfacechain);surfacechain++)
2249 surface->cached_dlight = true;
2254 R_UpdateAllTextureInfo(ent);
2255 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2260 if (ent == r_refdef.worldentity)
2262 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2264 if (!r_worldsurfacevisible[j])
2266 if (t != surface->texture)
2270 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2273 t = surface->texture;
2274 texture = t->currentframe;
2275 f = texture->currentmaterialflags & flagsmask;
2277 if (f && surface->num_triangles)
2279 // if lightmap parameters changed, rebuild lightmap texture
2280 if (surface->cached_dlight && surface->lightmapinfo->samples)
2281 R_BuildLightMap(ent, surface);
2282 // add face to draw list
2283 surfacelist[numsurfacelist++] = surface;
2284 counttriangles += surface->num_triangles;
2285 if (numsurfacelist >= maxsurfacelist)
2287 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2295 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2297 if (t != surface->texture)
2301 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2304 t = surface->texture;
2305 texture = t->currentframe;
2306 f = texture->currentmaterialflags & flagsmask;
2308 if (f && surface->num_triangles)
2310 // if lightmap parameters changed, rebuild lightmap texture
2311 if (surface->cached_dlight && surface->lightmapinfo->samples)
2312 R_BuildLightMap(ent, surface);
2313 // add face to draw list
2314 surfacelist[numsurfacelist++] = surface;
2315 counttriangles += surface->num_triangles;
2316 if (numsurfacelist >= maxsurfacelist)
2318 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2325 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2326 if (!r_showtrispass)
2327 renderstats.entities_triangles += counttriangles;