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", "shows triangle outlines, value controls brightness (can be above 1)"};
73 cvar_t r_showtris_polygonoffset = {0, "r_showtris_polygonoffset", "-10", "nudges triangle outlines in hardware depth units, used to make outlines appear infront of walls"};
74 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
75 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
76 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
77 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
78 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
79 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
80 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing\n"};
81 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
82 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
89 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
90 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
91 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
92 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
93 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
94 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
95 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
97 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
99 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
100 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
101 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
103 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
104 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
105 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
106 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
107 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
109 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
111 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
113 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
115 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
117 rtexturepool_t *r_main_texturepool;
118 rtexture_t *r_bloom_texture_screen;
119 rtexture_t *r_bloom_texture_bloom;
120 rtexture_t *r_texture_blanknormalmap;
121 rtexture_t *r_texture_white;
122 rtexture_t *r_texture_black;
123 rtexture_t *r_texture_notexture;
124 rtexture_t *r_texture_whitecube;
125 rtexture_t *r_texture_normalizationcube;
126 rtexture_t *r_texture_fogattenuation;
127 rtexture_t *r_texture_fogintensity;
129 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
132 for (i = 0;i < verts;i++)
143 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
146 for (i = 0;i < verts;i++)
161 vec_t fogtabledistmultiplier;
162 float fogtable[FOGTABLEWIDTH];
163 float fog_density, fog_red, fog_green, fog_blue;
165 qboolean oldgl_fogenable;
166 void R_UpdateFog(void)
168 if (gamemode == GAME_NEHAHRA)
170 if (gl_fogenable.integer)
172 oldgl_fogenable = true;
173 fog_density = gl_fogdensity.value;
174 fog_red = gl_fogred.value;
175 fog_green = gl_foggreen.value;
176 fog_blue = gl_fogblue.value;
178 else if (oldgl_fogenable)
180 oldgl_fogenable = false;
189 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
190 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
191 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
196 fogdensity = -4000.0f / (fog_density * fog_density);
197 // this is the point where the fog reaches 0.9986 alpha, which we
198 // consider a good enough cutoff point for the texture
199 // (0.9986 * 256 == 255.6)
200 fogrange = 400 / fog_density;
201 fograngerecip = 1.0f / fogrange;
202 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
203 // fog color was already set
209 // FIXME: move this to client?
212 if (gamemode == GAME_NEHAHRA)
214 Cvar_Set("gl_fogenable", "0");
215 Cvar_Set("gl_fogdensity", "0.2");
216 Cvar_Set("gl_fogred", "0.3");
217 Cvar_Set("gl_foggreen", "0.3");
218 Cvar_Set("gl_fogblue", "0.3");
220 fog_density = fog_red = fog_green = fog_blue = 0.0f;
223 // FIXME: move this to client?
224 void FOG_registercvars(void)
229 if (gamemode == GAME_NEHAHRA)
231 Cvar_RegisterVariable (&gl_fogenable);
232 Cvar_RegisterVariable (&gl_fogdensity);
233 Cvar_RegisterVariable (&gl_fogred);
234 Cvar_RegisterVariable (&gl_foggreen);
235 Cvar_RegisterVariable (&gl_fogblue);
236 Cvar_RegisterVariable (&gl_fogstart);
237 Cvar_RegisterVariable (&gl_fogend);
240 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
241 for (x = 0;x < FOGTABLEWIDTH;x++)
243 alpha = exp(r / ((double)x*(double)x));
244 if (x == FOGTABLEWIDTH - 1)
246 fogtable[x] = bound(0, alpha, 1);
250 static void R_BuildBlankTextures(void)
252 unsigned char data[4];
253 data[0] = 128; // normal X
254 data[1] = 128; // normal Y
255 data[2] = 255; // normal Z
256 data[3] = 128; // height
257 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
262 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
267 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
270 static void R_BuildNoTexture(void)
273 unsigned char pix[16][16][4];
274 // this makes a light grey/dark grey checkerboard texture
275 for (y = 0;y < 16;y++)
277 for (x = 0;x < 16;x++)
279 if ((y < 8) ^ (x < 8))
295 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
298 static void R_BuildWhiteCube(void)
300 unsigned char data[6*1*1*4];
301 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
302 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
303 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
304 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
305 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
306 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
307 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
310 static void R_BuildNormalizationCube(void)
314 vec_t s, t, intensity;
316 unsigned char data[6][NORMSIZE][NORMSIZE][4];
317 for (side = 0;side < 6;side++)
319 for (y = 0;y < NORMSIZE;y++)
321 for (x = 0;x < NORMSIZE;x++)
323 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
324 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
359 intensity = 127.0f / sqrt(DotProduct(v, v));
360 data[side][y][x][0] = 128.0f + intensity * v[0];
361 data[side][y][x][1] = 128.0f + intensity * v[1];
362 data[side][y][x][2] = 128.0f + intensity * v[2];
363 data[side][y][x][3] = 255;
367 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
370 static void R_BuildFogTexture(void)
375 unsigned char data1[FOGWIDTH][4];
376 unsigned char data2[FOGWIDTH][4];
377 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
378 for (x = 0;x < FOGWIDTH;x++)
380 alpha = exp(r / ((double)x*(double)x));
381 if (x == FOGWIDTH - 1)
383 b = (int)(256.0 * alpha);
384 b = bound(0, b, 255);
385 data1[x][0] = 255 - b;
386 data1[x][1] = 255 - b;
387 data1[x][2] = 255 - b;
394 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
395 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
398 void gl_main_start(void)
400 r_main_texturepool = R_AllocTexturePool();
401 r_bloom_texture_screen = NULL;
402 r_bloom_texture_bloom = NULL;
403 R_BuildBlankTextures();
405 if (gl_texturecubemap)
408 R_BuildNormalizationCube();
413 void gl_main_shutdown(void)
415 R_FreeTexturePool(&r_main_texturepool);
416 r_bloom_texture_screen = NULL;
417 r_bloom_texture_bloom = NULL;
418 r_texture_blanknormalmap = NULL;
419 r_texture_white = NULL;
420 r_texture_black = NULL;
421 r_texture_whitecube = NULL;
422 r_texture_normalizationcube = NULL;
425 extern void CL_ParseEntityLump(char *entitystring);
426 void gl_main_newmap(void)
428 // FIXME: move this code to client
430 char *entities, entname[MAX_QPATH];
434 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
435 l = (int)strlen(entname) - 4;
436 if (l >= 0 && !strcmp(entname + l, ".bsp"))
438 strcpy(entname + l, ".ent");
439 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
441 CL_ParseEntityLump(entities);
446 if (cl.worldmodel->brush.entities)
447 CL_ParseEntityLump(cl.worldmodel->brush.entities);
451 void GL_Main_Init(void)
453 Matrix4x4_CreateIdentity(&r_identitymatrix);
454 // FIXME: move this to client?
456 Cvar_RegisterVariable(&r_showtris);
457 Cvar_RegisterVariable(&r_showtris_polygonoffset);
458 Cvar_RegisterVariable(&r_shownormals);
459 Cvar_RegisterVariable(&r_showlighting);
460 Cvar_RegisterVariable(&r_showshadowvolumes);
461 Cvar_RegisterVariable(&r_showcollisionbrushes);
462 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
463 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
464 Cvar_RegisterVariable(&r_showdisabledepthtest);
465 Cvar_RegisterVariable(&r_drawentities);
466 Cvar_RegisterVariable(&r_drawviewmodel);
467 Cvar_RegisterVariable(&r_speeds);
468 Cvar_RegisterVariable(&r_fullbrights);
469 Cvar_RegisterVariable(&r_wateralpha);
470 Cvar_RegisterVariable(&r_dynamic);
471 Cvar_RegisterVariable(&r_fullbright);
472 Cvar_RegisterVariable(&r_textureunits);
473 Cvar_RegisterVariable(&r_lerpsprites);
474 Cvar_RegisterVariable(&r_lerpmodels);
475 Cvar_RegisterVariable(&r_waterscroll);
476 Cvar_RegisterVariable(&r_bloom);
477 Cvar_RegisterVariable(&r_bloom_intensity);
478 Cvar_RegisterVariable(&r_bloom_blur);
479 Cvar_RegisterVariable(&r_bloom_resolution);
480 Cvar_RegisterVariable(&r_bloom_power);
481 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
482 Cvar_RegisterVariable(&developer_texturelogging);
483 Cvar_RegisterVariable(&gl_lightmaps);
484 Cvar_RegisterVariable(&r_test);
485 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
486 Cvar_SetValue("r_fullbrights", 0);
487 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
490 static vec3_t r_farclip_origin;
491 static vec3_t r_farclip_direction;
492 static vec_t r_farclip_directiondist;
493 static vec_t r_farclip_meshfarclip;
494 static int r_farclip_directionbit0;
495 static int r_farclip_directionbit1;
496 static int r_farclip_directionbit2;
498 // enlarge farclip to accomodate box
499 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
502 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
503 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
504 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
505 if (r_farclip_meshfarclip < d)
506 r_farclip_meshfarclip = d;
509 // return farclip value
510 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
514 VectorCopy(origin, r_farclip_origin);
515 VectorCopy(direction, r_farclip_direction);
516 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
517 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
518 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
519 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
520 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
522 if (r_refdef.worldmodel)
523 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
524 for (i = 0;i < r_refdef.numentities;i++)
525 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
527 return r_farclip_meshfarclip - r_farclip_directiondist;
530 extern void R_Textures_Init(void);
531 extern void GL_Draw_Init(void);
532 extern void GL_Main_Init(void);
533 extern void R_Shadow_Init(void);
534 extern void R_Sky_Init(void);
535 extern void GL_Surf_Init(void);
536 extern void R_Crosshairs_Init(void);
537 extern void R_Light_Init(void);
538 extern void R_Particles_Init(void);
539 extern void R_Explosion_Init(void);
540 extern void gl_backend_init(void);
541 extern void Sbar_Init(void);
542 extern void R_LightningBeams_Init(void);
543 extern void Mod_RenderInit(void);
545 void Render_Init(void)
561 R_LightningBeams_Init();
570 extern char *ENGINE_EXTENSIONS;
573 VID_CheckExtensions();
575 // LordHavoc: report supported extensions
576 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
578 // clear to black (loading plaque will be seen over this)
579 qglClearColor(0,0,0,1);
580 qglClear(GL_COLOR_BUFFER_BIT);
583 int R_CullBox(const vec3_t mins, const vec3_t maxs)
587 for (i = 0;i < 4;i++)
594 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
598 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
602 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
606 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
610 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
614 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
618 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
622 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
630 //==================================================================================
632 static void R_MarkEntities (void)
635 entity_render_t *ent;
637 if (!r_drawentities.integer)
640 r_refdef.worldentity->visframe = r_framecount;
641 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
642 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
644 // worldmodel can check visibility
645 for (i = 0;i < r_refdef.numentities;i++)
647 ent = r_refdef.entities[i];
648 // some of the renderer still relies on origin...
649 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
650 // some of the renderer still relies on scale...
651 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
652 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)))
654 R_UpdateEntLights(ent);
655 ent->visframe = r_framecount;
661 // no worldmodel or it can't check visibility
662 for (i = 0;i < r_refdef.numentities;i++)
664 ent = r_refdef.entities[i];
665 // some of the renderer still relies on origin...
666 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
667 // some of the renderer still relies on scale...
668 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
669 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
671 R_UpdateEntLights(ent);
672 ent->visframe = r_framecount;
678 // only used if skyrendermasked, and normally returns false
679 int R_DrawBrushModelsSky (void)
682 entity_render_t *ent;
684 if (!r_drawentities.integer)
688 for (i = 0;i < r_refdef.numentities;i++)
690 ent = r_refdef.entities[i];
691 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
693 ent->model->DrawSky(ent);
700 void R_DrawNoModel(entity_render_t *ent);
701 void R_DrawModels(void)
704 entity_render_t *ent;
706 if (!r_drawentities.integer)
709 for (i = 0;i < r_refdef.numentities;i++)
711 ent = r_refdef.entities[i];
712 if (ent->visframe == r_framecount)
714 renderstats.entities++;
715 if (ent->model && ent->model->Draw != NULL)
716 ent->model->Draw(ent);
723 static void R_SetFrustum(void)
725 // break apart the view matrix into vectors for various purposes
726 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
727 VectorNegate(r_viewleft, r_viewright);
730 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
731 frustum[0].normal[1] = 0 - 0;
732 frustum[0].normal[2] = -1 - 0;
733 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
734 frustum[1].normal[1] = 0 + 0;
735 frustum[1].normal[2] = -1 + 0;
736 frustum[2].normal[0] = 0 - 0;
737 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
738 frustum[2].normal[2] = -1 - 0;
739 frustum[3].normal[0] = 0 + 0;
740 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
741 frustum[3].normal[2] = -1 + 0;
746 nudge = 1.0 - 1.0 / (1<<23);
747 frustum[4].normal[0] = 0 - 0;
748 frustum[4].normal[1] = 0 - 0;
749 frustum[4].normal[2] = -1 - -nudge;
750 frustum[4].dist = 0 - -2 * zNear * nudge;
751 frustum[5].normal[0] = 0 + 0;
752 frustum[5].normal[1] = 0 + 0;
753 frustum[5].normal[2] = -1 + -nudge;
754 frustum[5].dist = 0 + -2 * zNear * nudge;
760 frustum[0].normal[0] = m[3] - m[0];
761 frustum[0].normal[1] = m[7] - m[4];
762 frustum[0].normal[2] = m[11] - m[8];
763 frustum[0].dist = m[15] - m[12];
765 frustum[1].normal[0] = m[3] + m[0];
766 frustum[1].normal[1] = m[7] + m[4];
767 frustum[1].normal[2] = m[11] + m[8];
768 frustum[1].dist = m[15] + m[12];
770 frustum[2].normal[0] = m[3] - m[1];
771 frustum[2].normal[1] = m[7] - m[5];
772 frustum[2].normal[2] = m[11] - m[9];
773 frustum[2].dist = m[15] - m[13];
775 frustum[3].normal[0] = m[3] + m[1];
776 frustum[3].normal[1] = m[7] + m[5];
777 frustum[3].normal[2] = m[11] + m[9];
778 frustum[3].dist = m[15] + m[13];
780 frustum[4].normal[0] = m[3] - m[2];
781 frustum[4].normal[1] = m[7] - m[6];
782 frustum[4].normal[2] = m[11] - m[10];
783 frustum[4].dist = m[15] - m[14];
785 frustum[5].normal[0] = m[3] + m[2];
786 frustum[5].normal[1] = m[7] + m[6];
787 frustum[5].normal[2] = m[11] + m[10];
788 frustum[5].dist = m[15] + m[14];
793 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
794 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
795 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
796 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
797 VectorCopy(r_viewforward, frustum[4].normal);
798 VectorNormalize(frustum[0].normal);
799 VectorNormalize(frustum[1].normal);
800 VectorNormalize(frustum[2].normal);
801 VectorNormalize(frustum[3].normal);
802 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
803 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
804 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
805 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
806 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
807 PlaneClassify(&frustum[0]);
808 PlaneClassify(&frustum[1]);
809 PlaneClassify(&frustum[2]);
810 PlaneClassify(&frustum[3]);
811 PlaneClassify(&frustum[4]);
813 // LordHavoc: note to all quake engine coders, Quake had a special case
814 // for 90 degrees which assumed a square view (wrong), so I removed it,
815 // Quake2 has it disabled as well.
817 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
818 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
819 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
820 //PlaneClassify(&frustum[0]);
822 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
823 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
824 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
825 //PlaneClassify(&frustum[1]);
827 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
828 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
829 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
830 //PlaneClassify(&frustum[2]);
832 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
833 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
834 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
835 //PlaneClassify(&frustum[3]);
838 //VectorCopy(r_viewforward, frustum[4].normal);
839 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
840 //PlaneClassify(&frustum[4]);
843 static void R_BlendView(void)
845 int screenwidth, screenheight;
850 // set the (poorly named) screenwidth and screenheight variables to
851 // a power of 2 at least as large as the screen, these will define the
852 // size of the texture to allocate
853 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
854 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
856 doblend = r_refdef.viewblend[3] >= 0.01f;
857 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;
859 if (!dobloom && !doblend)
862 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
865 R_Mesh_Matrix(&r_identitymatrix);
866 // vertex coordinates for a quad that covers the screen exactly
867 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
868 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
869 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
870 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
873 int bloomwidth, bloomheight, x, dobloomblend, range;
874 float xoffset, yoffset, r;
876 // allocate textures as needed
877 if (!r_bloom_texture_screen)
878 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
879 if (!r_bloom_texture_bloom)
880 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
881 // set bloomwidth and bloomheight to the bloom resolution that will be
882 // used (often less than the screen resolution for faster rendering)
883 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
884 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
885 // set up a texcoord array for the full resolution screen image
886 // (we have to keep this around to copy back during final render)
887 varray_texcoord2f[0][0] = 0;
888 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
889 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
890 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
891 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
892 varray_texcoord2f[0][5] = 0;
893 varray_texcoord2f[0][6] = 0;
894 varray_texcoord2f[0][7] = 0;
895 // set up a texcoord array for the reduced resolution bloom image
896 // (which will be additive blended over the screen image)
897 varray_texcoord2f[1][0] = 0;
898 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
899 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
900 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
901 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
902 varray_texcoord2f[1][5] = 0;
903 varray_texcoord2f[1][6] = 0;
904 varray_texcoord2f[1][7] = 0;
905 memset(&m, 0, sizeof(m));
906 m.pointer_vertex = varray_vertex3f;
907 m.pointer_texcoord[0] = varray_texcoord2f[0];
908 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
910 // copy view into the full resolution screen image texture
912 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
913 renderstats.bloom_copypixels += r_view_width * r_view_height;
914 // now scale it down to the bloom size and raise to a power of itself
915 // to darken it (this leaves the really bright stuff bright, and
916 // everything else becomes very dark)
917 // TODO: optimize with multitexture or GLSL
918 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
919 GL_BlendFunc(GL_ONE, GL_ZERO);
920 GL_Color(1, 1, 1, 1);
921 R_Mesh_Draw(0, 4, 2, polygonelements);
922 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
923 // render multiple times with a multiply blendfunc to raise to a power
924 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
925 for (x = 1;x < r_bloom_power.integer;x++)
927 R_Mesh_Draw(0, 4, 2, polygonelements);
928 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
930 // we now have a darkened bloom image in the framebuffer, copy it into
931 // the bloom image texture for more processing
932 memset(&m, 0, sizeof(m));
933 m.pointer_vertex = varray_vertex3f;
934 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
935 m.pointer_texcoord[0] = varray_texcoord2f[2];
938 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
939 renderstats.bloom_copypixels += bloomwidth * bloomheight;
940 // blend on at multiple vertical offsets to achieve a vertical blur
941 // TODO: do offset blends using GLSL
942 range = r_bloom_blur.integer * bloomwidth / 320;
943 GL_BlendFunc(GL_ONE, GL_ZERO);
944 for (x = -range;x <= range;x++)
946 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
947 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
948 // compute a texcoord array with the specified x and y offset
949 varray_texcoord2f[2][0] = xoffset+0;
950 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
951 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
952 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
953 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
954 varray_texcoord2f[2][5] = yoffset+0;
955 varray_texcoord2f[2][6] = xoffset+0;
956 varray_texcoord2f[2][7] = yoffset+0;
957 // this r value looks like a 'dot' particle, fading sharply to
958 // black at the edges
959 // (probably not realistic but looks good enough)
960 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
963 GL_Color(r, r, r, 1);
964 R_Mesh_Draw(0, 4, 2, polygonelements);
965 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
966 GL_BlendFunc(GL_ONE, GL_ONE);
968 // copy the vertically blurred bloom view to a texture
970 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
971 renderstats.bloom_copypixels += bloomwidth * bloomheight;
972 // blend the vertically blurred image at multiple offsets horizontally
973 // to finish the blur effect
974 // TODO: do offset blends using GLSL
975 range = r_bloom_blur.integer * bloomwidth / 320;
976 GL_BlendFunc(GL_ONE, GL_ZERO);
977 for (x = -range;x <= range;x++)
979 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
980 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
981 // compute a texcoord array with the specified x and y offset
982 varray_texcoord2f[2][0] = xoffset+0;
983 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
984 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
985 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
986 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
987 varray_texcoord2f[2][5] = yoffset+0;
988 varray_texcoord2f[2][6] = xoffset+0;
989 varray_texcoord2f[2][7] = yoffset+0;
990 // this r value looks like a 'dot' particle, fading sharply to
991 // black at the edges
992 // (probably not realistic but looks good enough)
993 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
996 GL_Color(r, r, r, 1);
997 R_Mesh_Draw(0, 4, 2, polygonelements);
998 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
999 GL_BlendFunc(GL_ONE, GL_ONE);
1001 // copy the blurred bloom view to a texture
1002 GL_ActiveTexture(0);
1003 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1004 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1005 // go back to full view area
1006 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1007 // put the original screen image back in place and blend the bloom
1009 memset(&m, 0, sizeof(m));
1010 m.pointer_vertex = varray_vertex3f;
1011 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1012 m.pointer_texcoord[0] = varray_texcoord2f[0];
1014 dobloomblend = false;
1016 // do both in one pass if possible
1017 if (r_textureunits.integer >= 2 && gl_combine.integer)
1019 dobloomblend = false;
1020 m.texcombinergb[1] = GL_ADD;
1021 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1022 m.pointer_texcoord[1] = varray_texcoord2f[1];
1025 dobloomblend = true;
1028 GL_BlendFunc(GL_ONE, GL_ZERO);
1030 R_Mesh_Draw(0, 4, 2, polygonelements);
1031 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1032 // now blend on the bloom texture if multipass
1035 memset(&m, 0, sizeof(m));
1036 m.pointer_vertex = varray_vertex3f;
1037 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1038 m.pointer_texcoord[0] = varray_texcoord2f[1];
1040 GL_BlendFunc(GL_ONE, GL_ONE);
1042 R_Mesh_Draw(0, 4, 2, polygonelements);
1043 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1048 // apply a color tint to the whole view
1049 memset(&m, 0, sizeof(m));
1050 m.pointer_vertex = varray_vertex3f;
1052 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1053 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1054 R_Mesh_Draw(0, 4, 2, polygonelements);
1058 void R_RenderScene(void);
1060 matrix4x4_t r_waterscrollmatrix;
1067 void R_RenderView(void)
1069 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1070 return; //Host_Error ("R_RenderView: NULL worldmodel");
1072 r_view_width = bound(0, r_refdef.width, vid.width);
1073 r_view_height = bound(0, r_refdef.height, vid.height);
1075 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1076 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1078 r_view_matrix = r_refdef.viewentitymatrix;
1079 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1080 r_rtworld = r_shadow_realtime_world.integer;
1081 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1082 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1083 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1084 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1086 // GL is weird because it's bottom to top, r_view_y is top to bottom
1087 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1088 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1089 GL_ScissorTest(true);
1094 R_TimeReport("setup");
1096 qglDepthFunc(GL_LEQUAL);
1097 qglPolygonOffset(0, 0);
1098 qglEnable(GL_POLYGON_OFFSET_FILL);
1102 qglPolygonOffset(0, 0);
1103 qglDisable(GL_POLYGON_OFFSET_FILL);
1106 R_TimeReport("blendview");
1108 GL_Scissor(0, 0, vid.width, vid.height);
1109 GL_ScissorTest(false);
1113 void CSQC_R_ClearScreen (void)
1115 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1116 return; //Host_Error ("R_RenderView: NULL worldmodel");
1118 r_view_width = bound(0, r_refdef.width, vid.width);
1119 r_view_height = bound(0, r_refdef.height, vid.height);
1121 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1122 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1124 r_view_matrix = r_refdef.viewentitymatrix;
1125 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1126 r_rtworld = r_shadow_realtime_world.integer;
1127 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1128 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1129 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1130 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1132 // GL is weird because it's bottom to top, r_view_y is top to bottom
1133 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1134 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1135 GL_ScissorTest(true);
1140 R_TimeReport("setup");
1144 void CSQC_R_RenderScene (void)
1146 qglDepthFunc(GL_LEQUAL);
1147 qglPolygonOffset(0, 0);
1148 qglEnable(GL_POLYGON_OFFSET_FILL);
1152 qglPolygonOffset(0, 0);
1153 qglDisable(GL_POLYGON_OFFSET_FILL);
1156 R_TimeReport("blendview");
1158 GL_Scissor(0, 0, vid.width, vid.height);
1159 GL_ScissorTest(false);
1162 extern void R_DrawLightningBeams (void);
1163 extern void VM_AddPolygonsToMeshQueue (void);
1164 void R_RenderScene(void)
1166 // don't let sound skip if going slow
1167 if (r_refdef.extraupdate)
1172 R_MeshQueue_BeginScene();
1176 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1177 if (r_rtworldshadows || r_rtdlightshadows)
1178 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f);
1180 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f, r_farclip);
1182 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1184 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);
1188 R_WorldVisibility();
1189 R_TimeReport("worldvis");
1192 R_TimeReport("markentity");
1194 R_Shadow_UpdateWorldLightSelection();
1196 for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1202 GL_BlendFunc(GL_ONE, GL_ONE);
1203 GL_DepthTest(!r_showdisabledepthtest.integer);
1204 GL_DepthMask(GL_FALSE);
1205 memset(&m, 0, sizeof(m));
1207 //qglEnable(GL_LINE_SMOOTH);
1208 qglEnable(GL_POLYGON_OFFSET_LINE);
1209 qglPolygonOffset(0, r_showtris_polygonoffset.value);
1213 if (cl.csqc_vidvars.drawworld)
1215 // don't let sound skip if going slow
1216 if (r_refdef.extraupdate)
1219 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1220 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1222 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1223 R_TimeReport("worldsky");
1226 if (R_DrawBrushModelsSky())
1227 R_TimeReport("bmodelsky");
1229 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1230 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1232 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1233 R_TimeReport("world");
1236 R_DrawLightningBeams();
1237 R_TimeReport("lightning");
1240 R_TimeReport("particles");
1243 R_TimeReport("explosions");
1246 // don't let sound skip if going slow
1247 if (r_refdef.extraupdate)
1250 GL_ShowTrisColor(0, 0.015, 0, 1);
1253 R_TimeReport("models");
1255 // don't let sound skip if going slow
1256 if (r_refdef.extraupdate)
1259 GL_ShowTrisColor(0, 0, 0.033, 1);
1260 R_ShadowVolumeLighting(false);
1261 R_TimeReport("rtlights");
1263 // don't let sound skip if going slow
1264 if (r_refdef.extraupdate)
1267 GL_ShowTrisColor(0.1, 0, 0, 1);
1269 R_MeshQueue_RenderTransparent();
1270 R_TimeReport("drawtrans");
1272 if (cl.csqc_vidvars.drawworld)
1275 R_TimeReport("coronas");
1277 if(cl.csqc_vidvars.drawcrosshair)
1279 R_DrawWorldCrosshair();
1280 R_TimeReport("crosshair");
1283 VM_AddPolygonsToMeshQueue();
1285 R_MeshQueue_Render();
1289 //qglDisable(GL_LINE_SMOOTH);
1290 qglDisable(GL_POLYGON_OFFSET_LINE);
1296 R_MeshQueue_EndScene();
1298 // don't let sound skip if going slow
1299 if (r_refdef.extraupdate)
1304 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1307 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1309 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1310 GL_DepthMask(false);
1312 R_Mesh_Matrix(&r_identitymatrix);
1314 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1315 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1316 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1317 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1318 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1319 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1320 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1321 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1322 R_FillColors(color, 8, cr, cg, cb, ca);
1325 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1327 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1329 c[0] = c[0] * f1 + fogcolor[0] * f2;
1330 c[1] = c[1] * f1 + fogcolor[1] * f2;
1331 c[2] = c[2] * f1 + fogcolor[2] * f2;
1334 memset(&m, 0, sizeof(m));
1335 m.pointer_vertex = vertex3f;
1336 m.pointer_color = color;
1342 int nomodelelements[24] =
1354 float nomodelvertex3f[6*3] =
1364 float nomodelcolor4f[6*4] =
1366 0.0f, 0.0f, 0.5f, 1.0f,
1367 0.0f, 0.0f, 0.5f, 1.0f,
1368 0.0f, 0.5f, 0.0f, 1.0f,
1369 0.0f, 0.5f, 0.0f, 1.0f,
1370 0.5f, 0.0f, 0.0f, 1.0f,
1371 0.5f, 0.0f, 0.0f, 1.0f
1374 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
1380 R_Mesh_Matrix(&ent->matrix);
1382 memset(&m, 0, sizeof(m));
1383 m.pointer_vertex = nomodelvertex3f;
1385 if (ent->flags & EF_ADDITIVE)
1387 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1388 GL_DepthMask(false);
1390 else if (ent->alpha < 1)
1392 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1393 GL_DepthMask(false);
1397 GL_BlendFunc(GL_ONE, GL_ZERO);
1400 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1403 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1404 m.pointer_color = color4f;
1405 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1407 for (i = 0, c = color4f;i < 6;i++, c += 4)
1409 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1410 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1411 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1415 else if (ent->alpha != 1)
1417 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1418 m.pointer_color = color4f;
1419 for (i = 0, c = color4f;i < 6;i++, c += 4)
1423 m.pointer_color = nomodelcolor4f;
1425 R_Mesh_Draw(0, 6, 8, nomodelelements);
1428 void R_DrawNoModel(entity_render_t *ent)
1430 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1431 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1433 // R_DrawNoModelCallback(ent, 0);
1436 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1438 vec3_t right1, right2, diff, normal;
1440 VectorSubtract (org2, org1, normal);
1442 // calculate 'right' vector for start
1443 VectorSubtract (r_vieworigin, org1, diff);
1444 CrossProduct (normal, diff, right1);
1445 VectorNormalize (right1);
1447 // calculate 'right' vector for end
1448 VectorSubtract (r_vieworigin, org2, diff);
1449 CrossProduct (normal, diff, right2);
1450 VectorNormalize (right2);
1452 vert[ 0] = org1[0] + width * right1[0];
1453 vert[ 1] = org1[1] + width * right1[1];
1454 vert[ 2] = org1[2] + width * right1[2];
1455 vert[ 3] = org1[0] - width * right1[0];
1456 vert[ 4] = org1[1] - width * right1[1];
1457 vert[ 5] = org1[2] - width * right1[2];
1458 vert[ 6] = org2[0] - width * right2[0];
1459 vert[ 7] = org2[1] - width * right2[1];
1460 vert[ 8] = org2[2] - width * right2[2];
1461 vert[ 9] = org2[0] + width * right2[0];
1462 vert[10] = org2[1] + width * right2[1];
1463 vert[11] = org2[2] + width * right2[2];
1466 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1468 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)
1470 float fog = 0.0f, ifog;
1474 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1477 R_Mesh_Matrix(&r_identitymatrix);
1478 GL_BlendFunc(blendfunc1, blendfunc2);
1479 GL_DepthMask(false);
1480 GL_DepthTest(!depthdisable);
1482 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1483 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1484 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1485 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1486 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1487 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1488 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1489 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1490 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1491 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1492 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1493 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1495 memset(&m, 0, sizeof(m));
1496 m.tex[0] = R_GetTexture(texture);
1497 m.pointer_texcoord[0] = spritetexcoord2f;
1498 m.pointer_vertex = varray_vertex3f;
1500 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
1501 R_Mesh_Draw(0, 4, 2, polygonelements);
1503 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
1505 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
1506 GL_BlendFunc(blendfunc1, GL_ONE);
1507 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
1508 R_Mesh_Draw(0, 4, 2, polygonelements);
1512 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1516 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1517 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1519 if (i == mesh->numvertices)
1521 if (mesh->numvertices < mesh->maxvertices)
1523 VectorCopy(v, vertex3f);
1524 mesh->numvertices++;
1526 return mesh->numvertices;
1532 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1536 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1537 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1538 e = mesh->element3i + mesh->numtriangles * 3;
1539 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1541 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1542 if (mesh->numtriangles < mesh->maxtriangles)
1547 mesh->numtriangles++;
1549 element[1] = element[2];
1553 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1555 int planenum, planenum2;
1558 mplane_t *plane, *plane2;
1559 float temppoints[2][256*3];
1560 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1564 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1565 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1567 if (planenum2 == planenum)
1569 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);
1572 if (tempnumpoints < 3)
1574 // generate elements forming a triangle fan for this polygon
1575 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1579 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)
1581 texturelayer_t *layer;
1582 layer = t->currentlayers + t->currentnumlayers++;
1584 layer->depthmask = depthmask;
1585 layer->blendfunc1 = blendfunc1;
1586 layer->blendfunc2 = blendfunc2;
1587 layer->texture = texture;
1588 layer->texmatrix = *matrix;
1589 layer->color[0] = r;
1590 layer->color[1] = g;
1591 layer->color[2] = b;
1592 layer->color[3] = a;
1595 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1597 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1598 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1601 texture_t *texture = t;
1602 model_t *model = ent->model;
1603 int s = ent->skinnum;
1604 if ((unsigned int)s >= (unsigned int)model->numskins)
1606 if (model->skinscenes)
1608 if (model->skinscenes[s].framecount > 1)
1609 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1611 s = model->skinscenes[s].firstframe;
1614 t = t + s * model->num_surfaces;
1616 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];
1617 texture->currentframe = t;
1620 t->currentmaterialflags = t->basematerialflags;
1621 t->currentalpha = ent->alpha;
1622 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1623 t->currentalpha *= r_wateralpha.value;
1624 if (!(ent->flags & RENDER_LIGHT))
1625 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1626 if (ent->effects & EF_ADDITIVE)
1627 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1628 else if (t->currentalpha < 1)
1629 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1630 if (ent->effects & EF_NODEPTHTEST)
1631 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1632 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1633 t->currenttexmatrix = r_waterscrollmatrix;
1635 t->currenttexmatrix = r_identitymatrix;
1636 t->currentnumlayers = 0;
1637 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1639 if (gl_lightmaps.integer)
1640 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1641 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1643 // transparent sky would be ridiculous
1644 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1645 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1649 int blendfunc1, blendfunc2, depthmask;
1650 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1652 blendfunc1 = GL_SRC_ALPHA;
1653 blendfunc2 = GL_ONE;
1656 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1658 blendfunc1 = GL_SRC_ALPHA;
1659 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1664 blendfunc1 = GL_ONE;
1665 blendfunc2 = GL_ZERO;
1668 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1670 rtexture_t *currentbasetexture;
1672 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1673 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1674 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
1675 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1677 // fullbright is not affected by r_lightmapintensity
1678 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
1679 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1680 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
1681 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1682 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0], ent->colormap_shirtcolor[1] * ent->colormod[1], ent->colormap_shirtcolor[2] * ent->colormod[2], t->currentalpha);
1688 // q3bsp has no lightmap updates, so the lightstylevalue that
1689 // would normally be baked into the lightmaptexture must be
1690 // applied to the color
1691 if (ent->model->type == mod_brushq3)
1692 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1693 colorscale *= r_lightmapintensity;
1694 if (r_textureunits.integer >= 2 && gl_combine.integer)
1695 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);
1696 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1697 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);
1699 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);
1700 if (r_ambient.value >= (1.0f/64.0f))
1701 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);
1702 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1704 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
1705 if (r_ambient.value >= (1.0f/64.0f))
1706 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
1708 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1710 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
1711 if (r_ambient.value >= (1.0f/64.0f))
1712 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
1715 if (t->skin.glow != NULL)
1716 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
1717 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1719 // if this is opaque use alpha blend which will darken the earlier
1722 // if this is an alpha blended material, all the earlier passes
1723 // were darkened by fog already, so we only need to add the fog
1724 // color ontop through the fog mask texture
1726 // if this is an additive blended material, all the earlier passes
1727 // were darkened by fog already, and we should not add fog color
1728 // (because the background was not darkened, there is no fog color
1729 // that was lost behind it).
1730 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);
1737 void R_UpdateAllTextureInfo(entity_render_t *ent)
1741 for (i = 0;i < ent->model->num_textures;i++)
1742 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1745 float *rsurface_vertex3f;
1746 float *rsurface_svector3f;
1747 float *rsurface_tvector3f;
1748 float *rsurface_normal3f;
1749 float *rsurface_lightmapcolor4f;
1751 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1754 float center[3], forward[3], right[3], up[3], v[4][3];
1755 matrix4x4_t matrix1, imatrix1;
1756 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1758 rsurface_vertex3f = varray_vertex3f;
1759 rsurface_svector3f = NULL;
1760 rsurface_tvector3f = NULL;
1761 rsurface_normal3f = NULL;
1762 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1766 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1767 rsurface_svector3f = surface->groupmesh->data_svector3f;
1768 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1769 rsurface_normal3f = surface->groupmesh->data_normal3f;
1771 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1773 if (!rsurface_svector3f)
1775 rsurface_svector3f = varray_svector3f;
1776 rsurface_tvector3f = varray_tvector3f;
1777 rsurface_normal3f = varray_normal3f;
1778 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);
1780 // a single autosprite surface can contain multiple sprites...
1781 VectorClear(forward);
1783 VectorSet(up, 0, 0, 1);
1784 for (j = 0;j < surface->num_vertices - 3;j += 4)
1786 VectorClear(center);
1787 for (i = 0;i < 4;i++)
1788 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1789 VectorScale(center, 0.25f, center);
1790 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1791 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);
1792 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1793 for (i = 0;i < 4;i++)
1794 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1795 forward[0] = modelorg[0] - center[0];
1796 forward[1] = modelorg[1] - center[1];
1797 VectorNormalize(forward);
1798 right[0] = forward[1];
1799 right[1] = -forward[0];
1800 for (i = 0;i < 4;i++)
1801 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1803 rsurface_vertex3f = varray_vertex3f;
1804 rsurface_svector3f = NULL;
1805 rsurface_tvector3f = NULL;
1806 rsurface_normal3f = NULL;
1808 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1810 if (!rsurface_svector3f)
1812 rsurface_svector3f = varray_svector3f;
1813 rsurface_tvector3f = varray_tvector3f;
1814 rsurface_normal3f = varray_normal3f;
1815 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);
1817 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1818 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1819 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1820 // a single autosprite surface can contain multiple sprites...
1821 for (j = 0;j < surface->num_vertices - 3;j += 4)
1823 VectorClear(center);
1824 for (i = 0;i < 4;i++)
1825 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1826 VectorScale(center, 0.25f, center);
1827 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1828 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);
1829 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1830 for (i = 0;i < 4;i++)
1831 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1832 for (i = 0;i < 4;i++)
1833 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1835 rsurface_vertex3f = varray_vertex3f;
1836 rsurface_svector3f = NULL;
1837 rsurface_tvector3f = NULL;
1838 rsurface_normal3f = NULL;
1840 R_Mesh_VertexPointer(rsurface_vertex3f);
1843 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)
1851 vec4_t ambientcolor4f;
1852 vec3_t diffusecolor;
1853 vec3_t diffusenormal;
1854 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1856 rsurface_lightmapcolor4f = varray_color4f;
1857 if (rsurface_normal3f == NULL)
1859 rsurface_normal3f = varray_normal3f;
1860 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);
1862 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);
1871 r = ambientcolor4f[0];
1872 g = ambientcolor4f[1];
1873 b = ambientcolor4f[2];
1874 a = ambientcolor4f[3];
1875 rsurface_lightmapcolor4f = NULL;
1878 else if (lightmode >= 1)
1880 if (surface->lightmapinfo)
1882 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1884 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1887 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1888 VectorScale(lm, scale, c);
1889 if (surface->lightmapinfo->styles[1] != 255)
1891 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1893 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1894 VectorMA(c, scale, lm, c);
1895 if (surface->lightmapinfo->styles[2] != 255)
1898 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1899 VectorMA(c, scale, lm, c);
1900 if (surface->lightmapinfo->styles[3] != 255)
1903 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1904 VectorMA(c, scale, lm, c);
1912 rsurface_lightmapcolor4f = varray_color4f;
1915 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1918 rsurface_lightmapcolor4f = NULL;
1921 if (rsurface_lightmapcolor4f)
1923 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)
1925 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1934 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)
1936 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1943 rsurface_lightmapcolor4f = varray_color4f;
1945 if (applycolor && rsurface_lightmapcolor4f)
1947 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)
1954 rsurface_lightmapcolor4f = varray_color4f;
1956 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1957 GL_Color(r, g, b, a);
1960 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1962 int texturesurfaceindex;
1964 const msurface_t *surface;
1965 qboolean applycolor;
1967 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1969 renderstats.entities_surfaces += texturenumsurfaces;
1970 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1971 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1972 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1973 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
1974 qglDisable(GL_CULL_FACE);
1975 if (texture->currentnumlayers)
1978 texturelayer_t *layer;
1979 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1982 int layertexrgbscale;
1983 GL_DepthMask(layer->depthmask);
1984 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1985 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1987 layertexrgbscale = 4;
1988 VectorScale(layer->color, 0.25f, layercolor);
1990 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
1992 layertexrgbscale = 2;
1993 VectorScale(layer->color, 0.5f, layercolor);
1997 layertexrgbscale = 1;
1998 VectorScale(layer->color, 1.0f, layercolor);
2000 layercolor[3] = layer->color[3];
2001 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2002 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2003 switch (layer->type)
2005 case TEXTURELAYERTYPE_SKY:
2008 skyrendernow = false;
2009 if (skyrendermasked)
2012 // restore entity matrix and GL_Color
2013 R_Mesh_Matrix(&ent->matrix);
2014 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2017 // LordHavoc: HalfLife maps have freaky skypolys...
2018 //if (!ent->model->brush.ishlbsp)
2020 if (skyrendermasked)
2022 // depth-only (masking)
2023 GL_ColorMask(0,0,0,0);
2024 // just to make sure that braindead drivers don't draw anything
2025 // despite that colormask...
2026 GL_BlendFunc(GL_ZERO, GL_ONE);
2031 GL_BlendFunc(GL_ONE, GL_ZERO);
2033 memset(&m, 0, sizeof(m));
2035 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2037 surface = texturesurfacelist[texturesurfaceindex];
2038 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2039 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2040 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2041 GL_LockArrays(0, 0);
2043 if (skyrendermasked)
2044 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2047 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2048 memset(&m, 0, sizeof(m));
2049 m.tex[1] = R_GetTexture(layer->texture);
2050 m.texmatrix[1] = layer->texmatrix;
2051 m.texrgbscale[1] = layertexrgbscale;
2052 m.pointer_color = varray_color4f;
2054 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2056 surface = texturesurfacelist[texturesurfaceindex];
2057 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2058 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2059 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2062 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2063 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2065 else if (surface->lightmaptexture)
2067 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2068 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2072 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2073 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2075 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2076 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2077 GL_LockArrays(0, 0);
2080 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2081 memset(&m, 0, sizeof(m));
2082 m.tex[0] = R_GetTexture(layer->texture);
2083 m.texmatrix[0] = layer->texmatrix;
2084 m.pointer_color = varray_color4f;
2085 m.texrgbscale[0] = layertexrgbscale;
2087 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2089 surface = texturesurfacelist[texturesurfaceindex];
2090 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2091 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2094 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2095 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2097 else if (surface->lightmaptexture)
2099 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2100 R_Mesh_ColorPointer(NULL);
2104 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2105 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2107 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2108 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2109 GL_LockArrays(0, 0);
2111 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2112 memset(&m, 0, sizeof(m));
2113 m.tex[0] = R_GetTexture(layer->texture);
2114 m.texmatrix[0] = layer->texmatrix;
2115 m.pointer_color = varray_color4f;
2116 m.texrgbscale[0] = layertexrgbscale;
2118 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2120 surface = texturesurfacelist[texturesurfaceindex];
2121 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2122 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2123 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2124 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2125 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2126 GL_LockArrays(0, 0);
2129 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2130 memset(&m, 0, sizeof(m));
2131 m.tex[0] = R_GetTexture(layer->texture);
2132 m.texmatrix[0] = layer->texmatrix;
2133 m.texrgbscale[0] = layertexrgbscale;
2134 m.pointer_color = varray_color4f;
2136 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2138 surface = texturesurfacelist[texturesurfaceindex];
2139 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2140 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2141 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2142 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2143 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2144 GL_LockArrays(0, 0);
2147 case TEXTURELAYERTYPE_TEXTURE:
2148 memset(&m, 0, sizeof(m));
2149 m.tex[0] = R_GetTexture(layer->texture);
2150 m.texmatrix[0] = layer->texmatrix;
2151 m.pointer_color = varray_color4f;
2152 m.texrgbscale[0] = layertexrgbscale;
2154 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2156 surface = texturesurfacelist[texturesurfaceindex];
2157 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2158 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2159 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2160 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2161 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2162 GL_LockArrays(0, 0);
2165 case TEXTURELAYERTYPE_FOG:
2166 memset(&m, 0, sizeof(m));
2169 m.tex[0] = R_GetTexture(layer->texture);
2170 m.texmatrix[0] = layer->texmatrix;
2173 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2177 surface = texturesurfacelist[texturesurfaceindex];
2178 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2180 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2181 R_Mesh_ColorPointer(varray_color4f);
2182 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)
2184 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2185 c[0] = layercolor[0];
2186 c[1] = layercolor[1];
2187 c[2] = layercolor[2];
2188 c[3] = f * layercolor[3];
2190 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2191 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2192 GL_LockArrays(0, 0);
2196 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2198 // if trying to do overbright on first pass of an opaque surface
2199 // when combine is not supported, brighten as a post process
2200 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2203 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2204 GL_Color(1, 1, 1, 1);
2205 memset(&m, 0, sizeof(m));
2207 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2209 surface = texturesurfacelist[texturesurfaceindex];
2210 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2211 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2212 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2213 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2214 GL_LockArrays(0, 0);
2218 if (r_shownormals.integer && !r_showtrispass)
2222 GL_DepthTest(!r_showdisabledepthtest.integer);
2223 GL_DepthMask(texture->currentlayers->depthmask);
2224 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
2225 memset(&m, 0, sizeof(m));
2227 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2229 surface = texturesurfacelist[texturesurfaceindex];
2230 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2231 if (!rsurface_svector3f)
2233 rsurface_svector3f = varray_svector3f;
2234 rsurface_tvector3f = varray_tvector3f;
2235 rsurface_normal3f = varray_normal3f;
2236 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);
2238 GL_Color(1, 0, 0, 1);
2240 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2242 VectorCopy(rsurface_vertex3f + k * 3, v);
2243 qglVertex3f(v[0], v[1], v[2]);
2244 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
2245 qglVertex3f(v[0], v[1], v[2]);
2247 GL_Color(0, 0, 1, 1);
2248 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2250 VectorCopy(rsurface_vertex3f + k * 3, v);
2251 qglVertex3f(v[0], v[1], v[2]);
2252 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
2253 qglVertex3f(v[0], v[1], v[2]);
2255 GL_Color(0, 1, 0, 1);
2256 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2258 VectorCopy(rsurface_vertex3f + k * 3, v);
2259 qglVertex3f(v[0], v[1], v[2]);
2260 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
2261 qglVertex3f(v[0], v[1], v[2]);
2267 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2268 qglEnable(GL_CULL_FACE);
2271 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2273 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
2277 texture = surface->texture;
2278 if (texture->basematerialflags & MATERIALFLAG_SKY)
2279 return; // transparent sky is too difficult
2280 R_UpdateTextureInfo(ent, texture);
2282 R_Mesh_Matrix(&ent->matrix);
2283 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2284 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2287 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2289 int texturesurfaceindex;
2290 const msurface_t *surface;
2291 vec3_t tempcenter, center;
2292 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2294 // drawing sky transparently would be too difficult
2295 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2297 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2299 surface = texturesurfacelist[texturesurfaceindex];
2300 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2301 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2302 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2303 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2304 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
2309 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2312 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2313 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2315 int i, j, f, flagsmask;
2316 int counttriangles = 0;
2317 msurface_t *surface, **surfacechain;
2318 texture_t *t, *texture;
2319 model_t *model = ent->model;
2321 const int maxsurfacelist = 1024;
2322 int numsurfacelist = 0;
2323 const msurface_t *surfacelist[1024];
2326 R_Mesh_Matrix(&ent->matrix);
2327 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2329 // update light styles
2330 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2332 for (i = 0;i < model->brushq1.light_styles;i++)
2334 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2336 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2337 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2338 for (;(surface = *surfacechain);surfacechain++)
2339 surface->cached_dlight = true;
2344 R_UpdateAllTextureInfo(ent);
2345 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2350 if (ent == r_refdef.worldentity)
2352 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2354 if (!r_worldsurfacevisible[j])
2356 if (t != surface->texture)
2360 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2363 t = surface->texture;
2364 texture = t->currentframe;
2365 f = texture->currentmaterialflags & flagsmask;
2367 if (f && surface->num_triangles)
2369 // if lightmap parameters changed, rebuild lightmap texture
2370 if (surface->cached_dlight && surface->lightmapinfo->samples)
2371 R_BuildLightMap(ent, surface);
2372 // add face to draw list
2373 surfacelist[numsurfacelist++] = surface;
2374 counttriangles += surface->num_triangles;
2375 if (numsurfacelist >= maxsurfacelist)
2377 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2385 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2387 if (t != surface->texture)
2391 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2394 t = surface->texture;
2395 texture = t->currentframe;
2396 f = texture->currentmaterialflags & flagsmask;
2398 if (f && surface->num_triangles)
2400 // if lightmap parameters changed, rebuild lightmap texture
2401 if (surface->cached_dlight && surface->lightmapinfo->samples)
2402 R_BuildLightMap(ent, surface);
2403 // add face to draw list
2404 surfacelist[numsurfacelist++] = surface;
2405 counttriangles += surface->num_triangles;
2406 if (numsurfacelist >= maxsurfacelist)
2408 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2415 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2416 if (!r_showtrispass)
2417 renderstats.entities_triangles += counttriangles;