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");
1237 // don't let sound skip if going slow
1238 if (r_refdef.extraupdate)
1241 GL_ShowTrisColor(0, 0.015, 0, 1);
1244 R_TimeReport("models");
1246 // don't let sound skip if going slow
1247 if (r_refdef.extraupdate)
1250 GL_ShowTrisColor(0, 0, 0.033, 1);
1251 R_ShadowVolumeLighting(false);
1252 R_TimeReport("rtlights");
1254 // don't let sound skip if going slow
1255 if (r_refdef.extraupdate)
1258 GL_ShowTrisColor(0.1, 0, 0, 1);
1260 if (cl.csqc_vidvars.drawworld)
1262 R_DrawLightningBeams();
1263 R_TimeReport("lightning");
1266 R_TimeReport("particles");
1269 R_TimeReport("explosions");
1272 R_MeshQueue_RenderTransparent();
1273 R_TimeReport("drawtrans");
1275 if (cl.csqc_vidvars.drawworld)
1278 R_TimeReport("coronas");
1280 if(cl.csqc_vidvars.drawcrosshair)
1282 R_DrawWorldCrosshair();
1283 R_TimeReport("crosshair");
1286 VM_AddPolygonsToMeshQueue();
1288 R_MeshQueue_Render();
1292 //qglDisable(GL_LINE_SMOOTH);
1293 qglDisable(GL_POLYGON_OFFSET_LINE);
1299 R_MeshQueue_EndScene();
1301 // don't let sound skip if going slow
1302 if (r_refdef.extraupdate)
1307 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1310 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1312 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1313 GL_DepthMask(false);
1315 R_Mesh_Matrix(&r_identitymatrix);
1317 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1318 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1319 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1320 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1321 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1322 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1323 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1324 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1325 R_FillColors(color, 8, cr, cg, cb, ca);
1328 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1330 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1332 c[0] = c[0] * f1 + fogcolor[0] * f2;
1333 c[1] = c[1] * f1 + fogcolor[1] * f2;
1334 c[2] = c[2] * f1 + fogcolor[2] * f2;
1337 memset(&m, 0, sizeof(m));
1338 m.pointer_vertex = vertex3f;
1339 m.pointer_color = color;
1345 int nomodelelements[24] =
1357 float nomodelvertex3f[6*3] =
1367 float nomodelcolor4f[6*4] =
1369 0.0f, 0.0f, 0.5f, 1.0f,
1370 0.0f, 0.0f, 0.5f, 1.0f,
1371 0.0f, 0.5f, 0.0f, 1.0f,
1372 0.0f, 0.5f, 0.0f, 1.0f,
1373 0.5f, 0.0f, 0.0f, 1.0f,
1374 0.5f, 0.0f, 0.0f, 1.0f
1377 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
1383 R_Mesh_Matrix(&ent->matrix);
1385 memset(&m, 0, sizeof(m));
1386 m.pointer_vertex = nomodelvertex3f;
1388 if (ent->flags & EF_ADDITIVE)
1390 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1391 GL_DepthMask(false);
1393 else if (ent->alpha < 1)
1395 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1396 GL_DepthMask(false);
1400 GL_BlendFunc(GL_ONE, GL_ZERO);
1403 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1406 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1407 m.pointer_color = color4f;
1408 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1410 for (i = 0, c = color4f;i < 6;i++, c += 4)
1412 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1413 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1414 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1418 else if (ent->alpha != 1)
1420 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1421 m.pointer_color = color4f;
1422 for (i = 0, c = color4f;i < 6;i++, c += 4)
1426 m.pointer_color = nomodelcolor4f;
1428 R_Mesh_Draw(0, 6, 8, nomodelelements);
1431 void R_DrawNoModel(entity_render_t *ent)
1433 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1434 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1436 // R_DrawNoModelCallback(ent, 0);
1439 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1441 vec3_t right1, right2, diff, normal;
1443 VectorSubtract (org2, org1, normal);
1445 // calculate 'right' vector for start
1446 VectorSubtract (r_vieworigin, org1, diff);
1447 CrossProduct (normal, diff, right1);
1448 VectorNormalize (right1);
1450 // calculate 'right' vector for end
1451 VectorSubtract (r_vieworigin, org2, diff);
1452 CrossProduct (normal, diff, right2);
1453 VectorNormalize (right2);
1455 vert[ 0] = org1[0] + width * right1[0];
1456 vert[ 1] = org1[1] + width * right1[1];
1457 vert[ 2] = org1[2] + width * right1[2];
1458 vert[ 3] = org1[0] - width * right1[0];
1459 vert[ 4] = org1[1] - width * right1[1];
1460 vert[ 5] = org1[2] - width * right1[2];
1461 vert[ 6] = org2[0] - width * right2[0];
1462 vert[ 7] = org2[1] - width * right2[1];
1463 vert[ 8] = org2[2] - width * right2[2];
1464 vert[ 9] = org2[0] + width * right2[0];
1465 vert[10] = org2[1] + width * right2[1];
1466 vert[11] = org2[2] + width * right2[2];
1469 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1471 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)
1473 float fog = 0.0f, ifog;
1477 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1480 R_Mesh_Matrix(&r_identitymatrix);
1481 GL_BlendFunc(blendfunc1, blendfunc2);
1482 GL_DepthMask(false);
1483 GL_DepthTest(!depthdisable);
1485 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1486 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1487 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1488 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1489 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1490 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1491 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1492 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1493 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1494 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1495 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1496 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1498 memset(&m, 0, sizeof(m));
1499 m.tex[0] = R_GetTexture(texture);
1500 m.pointer_texcoord[0] = spritetexcoord2f;
1501 m.pointer_vertex = varray_vertex3f;
1503 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
1504 R_Mesh_Draw(0, 4, 2, polygonelements);
1506 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
1508 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
1509 GL_BlendFunc(blendfunc1, GL_ONE);
1510 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
1511 R_Mesh_Draw(0, 4, 2, polygonelements);
1515 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1519 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1520 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1522 if (i == mesh->numvertices)
1524 if (mesh->numvertices < mesh->maxvertices)
1526 VectorCopy(v, vertex3f);
1527 mesh->numvertices++;
1529 return mesh->numvertices;
1535 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1539 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1540 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1541 e = mesh->element3i + mesh->numtriangles * 3;
1542 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1544 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1545 if (mesh->numtriangles < mesh->maxtriangles)
1550 mesh->numtriangles++;
1552 element[1] = element[2];
1556 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1558 int planenum, planenum2;
1561 mplane_t *plane, *plane2;
1562 float temppoints[2][256*3];
1563 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1567 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1568 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1570 if (planenum2 == planenum)
1572 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);
1575 if (tempnumpoints < 3)
1577 // generate elements forming a triangle fan for this polygon
1578 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1582 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)
1584 texturelayer_t *layer;
1585 layer = t->currentlayers + t->currentnumlayers++;
1587 layer->depthmask = depthmask;
1588 layer->blendfunc1 = blendfunc1;
1589 layer->blendfunc2 = blendfunc2;
1590 layer->texture = texture;
1591 layer->texmatrix = *matrix;
1592 layer->color[0] = r;
1593 layer->color[1] = g;
1594 layer->color[2] = b;
1595 layer->color[3] = a;
1598 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1600 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1601 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1604 texture_t *texture = t;
1605 model_t *model = ent->model;
1606 int s = ent->skinnum;
1607 if ((unsigned int)s >= (unsigned int)model->numskins)
1609 if (model->skinscenes)
1611 if (model->skinscenes[s].framecount > 1)
1612 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1614 s = model->skinscenes[s].firstframe;
1617 t = t + s * model->num_surfaces;
1619 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];
1620 texture->currentframe = t;
1623 t->currentmaterialflags = t->basematerialflags;
1624 t->currentalpha = ent->alpha;
1625 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1626 t->currentalpha *= r_wateralpha.value;
1627 if (!(ent->flags & RENDER_LIGHT))
1628 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1629 if (ent->effects & EF_ADDITIVE)
1630 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1631 else if (t->currentalpha < 1)
1632 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1633 if (ent->effects & EF_NODEPTHTEST)
1634 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1635 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1636 t->currenttexmatrix = r_waterscrollmatrix;
1638 t->currenttexmatrix = r_identitymatrix;
1639 t->currentnumlayers = 0;
1640 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1642 if (gl_lightmaps.integer)
1643 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1644 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1646 // transparent sky would be ridiculous
1647 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1648 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1652 int blendfunc1, blendfunc2, depthmask;
1653 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1655 blendfunc1 = GL_SRC_ALPHA;
1656 blendfunc2 = GL_ONE;
1659 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1661 blendfunc1 = GL_SRC_ALPHA;
1662 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1667 blendfunc1 = GL_ONE;
1668 blendfunc2 = GL_ZERO;
1671 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1673 rtexture_t *currentbasetexture;
1675 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1676 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1677 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
1678 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1680 // fullbright is not affected by r_lightmapintensity
1681 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
1682 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1683 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);
1684 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1685 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);
1691 // q3bsp has no lightmap updates, so the lightstylevalue that
1692 // would normally be baked into the lightmaptexture must be
1693 // applied to the color
1694 if (ent->model->type == mod_brushq3)
1695 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1696 colorscale *= r_lightmapintensity;
1697 if (r_textureunits.integer >= 2 && gl_combine.integer)
1698 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);
1699 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1700 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);
1702 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);
1703 if (r_ambient.value >= (1.0f/64.0f))
1704 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);
1705 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1707 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);
1708 if (r_ambient.value >= (1.0f/64.0f))
1709 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);
1711 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1713 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);
1714 if (r_ambient.value >= (1.0f/64.0f))
1715 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);
1718 if (t->skin.glow != NULL)
1719 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
1720 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1722 // if this is opaque use alpha blend which will darken the earlier
1725 // if this is an alpha blended material, all the earlier passes
1726 // were darkened by fog already, so we only need to add the fog
1727 // color ontop through the fog mask texture
1729 // if this is an additive blended material, all the earlier passes
1730 // were darkened by fog already, and we should not add fog color
1731 // (because the background was not darkened, there is no fog color
1732 // that was lost behind it).
1733 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);
1740 void R_UpdateAllTextureInfo(entity_render_t *ent)
1744 for (i = 0;i < ent->model->num_textures;i++)
1745 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1748 float *rsurface_vertex3f;
1749 float *rsurface_svector3f;
1750 float *rsurface_tvector3f;
1751 float *rsurface_normal3f;
1752 float *rsurface_lightmapcolor4f;
1754 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1757 float center[3], forward[3], right[3], up[3], v[4][3];
1758 matrix4x4_t matrix1, imatrix1;
1759 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1761 rsurface_vertex3f = varray_vertex3f;
1762 rsurface_svector3f = NULL;
1763 rsurface_tvector3f = NULL;
1764 rsurface_normal3f = NULL;
1765 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1769 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1770 rsurface_svector3f = surface->groupmesh->data_svector3f;
1771 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1772 rsurface_normal3f = surface->groupmesh->data_normal3f;
1774 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1776 if (!rsurface_svector3f)
1778 rsurface_svector3f = varray_svector3f;
1779 rsurface_tvector3f = varray_tvector3f;
1780 rsurface_normal3f = varray_normal3f;
1781 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);
1783 // a single autosprite surface can contain multiple sprites...
1784 VectorClear(forward);
1786 VectorSet(up, 0, 0, 1);
1787 for (j = 0;j < surface->num_vertices - 3;j += 4)
1789 VectorClear(center);
1790 for (i = 0;i < 4;i++)
1791 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1792 VectorScale(center, 0.25f, center);
1793 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1794 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);
1795 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1796 for (i = 0;i < 4;i++)
1797 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1798 forward[0] = modelorg[0] - center[0];
1799 forward[1] = modelorg[1] - center[1];
1800 VectorNormalize(forward);
1801 right[0] = forward[1];
1802 right[1] = -forward[0];
1803 for (i = 0;i < 4;i++)
1804 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1806 rsurface_vertex3f = varray_vertex3f;
1807 rsurface_svector3f = NULL;
1808 rsurface_tvector3f = NULL;
1809 rsurface_normal3f = NULL;
1811 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1813 if (!rsurface_svector3f)
1815 rsurface_svector3f = varray_svector3f;
1816 rsurface_tvector3f = varray_tvector3f;
1817 rsurface_normal3f = varray_normal3f;
1818 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);
1820 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1821 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1822 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1823 // a single autosprite surface can contain multiple sprites...
1824 for (j = 0;j < surface->num_vertices - 3;j += 4)
1826 VectorClear(center);
1827 for (i = 0;i < 4;i++)
1828 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1829 VectorScale(center, 0.25f, center);
1830 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1831 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);
1832 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1833 for (i = 0;i < 4;i++)
1834 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1835 for (i = 0;i < 4;i++)
1836 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1838 rsurface_vertex3f = varray_vertex3f;
1839 rsurface_svector3f = NULL;
1840 rsurface_tvector3f = NULL;
1841 rsurface_normal3f = NULL;
1843 R_Mesh_VertexPointer(rsurface_vertex3f);
1846 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)
1854 vec4_t ambientcolor4f;
1855 vec3_t diffusecolor;
1856 vec3_t diffusenormal;
1857 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1859 rsurface_lightmapcolor4f = varray_color4f;
1860 if (rsurface_normal3f == NULL)
1862 rsurface_normal3f = varray_normal3f;
1863 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);
1865 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);
1874 r = ambientcolor4f[0];
1875 g = ambientcolor4f[1];
1876 b = ambientcolor4f[2];
1877 a = ambientcolor4f[3];
1878 rsurface_lightmapcolor4f = NULL;
1881 else if (lightmode >= 1)
1883 if (surface->lightmapinfo)
1885 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1887 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1890 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1891 VectorScale(lm, scale, c);
1892 if (surface->lightmapinfo->styles[1] != 255)
1894 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1896 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1897 VectorMA(c, scale, lm, c);
1898 if (surface->lightmapinfo->styles[2] != 255)
1901 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1902 VectorMA(c, scale, lm, c);
1903 if (surface->lightmapinfo->styles[3] != 255)
1906 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1907 VectorMA(c, scale, lm, c);
1915 rsurface_lightmapcolor4f = varray_color4f;
1918 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1921 rsurface_lightmapcolor4f = NULL;
1924 if (rsurface_lightmapcolor4f)
1926 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)
1928 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1937 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)
1939 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1946 rsurface_lightmapcolor4f = varray_color4f;
1948 if (applycolor && rsurface_lightmapcolor4f)
1950 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)
1957 rsurface_lightmapcolor4f = varray_color4f;
1959 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1960 GL_Color(r, g, b, a);
1963 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1965 int texturesurfaceindex;
1967 const msurface_t *surface;
1968 qboolean applycolor;
1970 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1972 renderstats.entities_surfaces += texturenumsurfaces;
1973 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1974 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1975 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1976 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
1977 qglDisable(GL_CULL_FACE);
1978 if (texture->currentnumlayers)
1981 texturelayer_t *layer;
1982 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1985 int layertexrgbscale;
1986 GL_DepthMask(layer->depthmask);
1987 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1988 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1990 layertexrgbscale = 4;
1991 VectorScale(layer->color, 0.25f, layercolor);
1993 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
1995 layertexrgbscale = 2;
1996 VectorScale(layer->color, 0.5f, layercolor);
2000 layertexrgbscale = 1;
2001 VectorScale(layer->color, 1.0f, layercolor);
2003 layercolor[3] = layer->color[3];
2004 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2005 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2006 switch (layer->type)
2008 case TEXTURELAYERTYPE_SKY:
2011 skyrendernow = false;
2012 if (skyrendermasked)
2015 // restore entity matrix and GL_Color
2016 R_Mesh_Matrix(&ent->matrix);
2017 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2020 // LordHavoc: HalfLife maps have freaky skypolys...
2021 //if (!ent->model->brush.ishlbsp)
2023 if (skyrendermasked)
2025 // depth-only (masking)
2026 GL_ColorMask(0,0,0,0);
2027 // just to make sure that braindead drivers don't draw anything
2028 // despite that colormask...
2029 GL_BlendFunc(GL_ZERO, GL_ONE);
2034 GL_BlendFunc(GL_ONE, GL_ZERO);
2036 memset(&m, 0, sizeof(m));
2038 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2040 surface = texturesurfacelist[texturesurfaceindex];
2041 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2042 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2043 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2044 GL_LockArrays(0, 0);
2046 if (skyrendermasked)
2047 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2050 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2051 memset(&m, 0, sizeof(m));
2052 m.tex[1] = R_GetTexture(layer->texture);
2053 m.texmatrix[1] = layer->texmatrix;
2054 m.texrgbscale[1] = layertexrgbscale;
2055 m.pointer_color = varray_color4f;
2057 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2059 surface = texturesurfacelist[texturesurfaceindex];
2060 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2061 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2062 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2065 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2066 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2068 else if (surface->lightmaptexture)
2070 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2071 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2075 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2076 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2078 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2079 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2080 GL_LockArrays(0, 0);
2083 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2084 memset(&m, 0, sizeof(m));
2085 m.tex[0] = R_GetTexture(layer->texture);
2086 m.texmatrix[0] = layer->texmatrix;
2087 m.pointer_color = varray_color4f;
2088 m.texrgbscale[0] = layertexrgbscale;
2090 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2092 surface = texturesurfacelist[texturesurfaceindex];
2093 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2094 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2097 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2098 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2100 else if (surface->lightmaptexture)
2102 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2103 R_Mesh_ColorPointer(NULL);
2107 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2108 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2110 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2111 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2112 GL_LockArrays(0, 0);
2114 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2115 memset(&m, 0, sizeof(m));
2116 m.tex[0] = R_GetTexture(layer->texture);
2117 m.texmatrix[0] = layer->texmatrix;
2118 m.pointer_color = varray_color4f;
2119 m.texrgbscale[0] = layertexrgbscale;
2121 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2123 surface = texturesurfacelist[texturesurfaceindex];
2124 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2125 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2126 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2127 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2128 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2129 GL_LockArrays(0, 0);
2132 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2133 memset(&m, 0, sizeof(m));
2134 m.tex[0] = R_GetTexture(layer->texture);
2135 m.texmatrix[0] = layer->texmatrix;
2136 m.texrgbscale[0] = layertexrgbscale;
2137 m.pointer_color = varray_color4f;
2139 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2141 surface = texturesurfacelist[texturesurfaceindex];
2142 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2143 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2144 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2145 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2146 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2147 GL_LockArrays(0, 0);
2150 case TEXTURELAYERTYPE_TEXTURE:
2151 memset(&m, 0, sizeof(m));
2152 m.tex[0] = R_GetTexture(layer->texture);
2153 m.texmatrix[0] = layer->texmatrix;
2154 m.pointer_color = varray_color4f;
2155 m.texrgbscale[0] = layertexrgbscale;
2157 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2159 surface = texturesurfacelist[texturesurfaceindex];
2160 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2161 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2162 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2163 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2164 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2165 GL_LockArrays(0, 0);
2168 case TEXTURELAYERTYPE_FOG:
2169 memset(&m, 0, sizeof(m));
2172 m.tex[0] = R_GetTexture(layer->texture);
2173 m.texmatrix[0] = layer->texmatrix;
2176 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2180 surface = texturesurfacelist[texturesurfaceindex];
2181 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2183 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2184 R_Mesh_ColorPointer(varray_color4f);
2185 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)
2187 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2188 c[0] = layercolor[0];
2189 c[1] = layercolor[1];
2190 c[2] = layercolor[2];
2191 c[3] = f * layercolor[3];
2193 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2194 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2195 GL_LockArrays(0, 0);
2199 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2201 // if trying to do overbright on first pass of an opaque surface
2202 // when combine is not supported, brighten as a post process
2203 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2206 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2207 GL_Color(1, 1, 1, 1);
2208 memset(&m, 0, sizeof(m));
2210 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2212 surface = texturesurfacelist[texturesurfaceindex];
2213 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2214 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2215 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2216 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2217 GL_LockArrays(0, 0);
2221 if (r_shownormals.integer && !r_showtrispass)
2225 GL_DepthTest(!r_showdisabledepthtest.integer);
2226 GL_DepthMask(texture->currentlayers->depthmask);
2227 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
2228 memset(&m, 0, sizeof(m));
2230 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2232 surface = texturesurfacelist[texturesurfaceindex];
2233 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2234 if (!rsurface_svector3f)
2236 rsurface_svector3f = varray_svector3f;
2237 rsurface_tvector3f = varray_tvector3f;
2238 rsurface_normal3f = varray_normal3f;
2239 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);
2241 GL_Color(1, 0, 0, 1);
2243 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2245 VectorCopy(rsurface_vertex3f + k * 3, v);
2246 qglVertex3f(v[0], v[1], v[2]);
2247 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
2248 qglVertex3f(v[0], v[1], v[2]);
2250 GL_Color(0, 0, 1, 1);
2251 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2253 VectorCopy(rsurface_vertex3f + k * 3, v);
2254 qglVertex3f(v[0], v[1], v[2]);
2255 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
2256 qglVertex3f(v[0], v[1], v[2]);
2258 GL_Color(0, 1, 0, 1);
2259 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2261 VectorCopy(rsurface_vertex3f + k * 3, v);
2262 qglVertex3f(v[0], v[1], v[2]);
2263 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
2264 qglVertex3f(v[0], v[1], v[2]);
2270 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2271 qglEnable(GL_CULL_FACE);
2274 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2276 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
2280 texture = surface->texture;
2281 if (texture->basematerialflags & MATERIALFLAG_SKY)
2282 return; // transparent sky is too difficult
2283 R_UpdateTextureInfo(ent, texture);
2285 R_Mesh_Matrix(&ent->matrix);
2286 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2287 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2290 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2292 int texturesurfaceindex;
2293 const msurface_t *surface;
2294 vec3_t tempcenter, center;
2295 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2297 // drawing sky transparently would be too difficult
2298 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2300 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2302 surface = texturesurfacelist[texturesurfaceindex];
2303 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2304 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2305 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2306 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2307 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
2312 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2315 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2316 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2318 int i, j, f, flagsmask;
2319 int counttriangles = 0;
2320 msurface_t *surface, **surfacechain;
2321 texture_t *t, *texture;
2322 model_t *model = ent->model;
2324 const int maxsurfacelist = 1024;
2325 int numsurfacelist = 0;
2326 const msurface_t *surfacelist[1024];
2329 R_Mesh_Matrix(&ent->matrix);
2330 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2332 // update light styles
2333 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2335 for (i = 0;i < model->brushq1.light_styles;i++)
2337 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2339 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2340 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2341 for (;(surface = *surfacechain);surfacechain++)
2342 surface->cached_dlight = true;
2347 R_UpdateAllTextureInfo(ent);
2348 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2353 if (ent == r_refdef.worldentity)
2355 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2357 if (!r_worldsurfacevisible[j])
2359 if (t != surface->texture)
2363 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2366 t = surface->texture;
2367 texture = t->currentframe;
2368 f = texture->currentmaterialflags & flagsmask;
2370 if (f && surface->num_triangles)
2372 // if lightmap parameters changed, rebuild lightmap texture
2373 if (surface->cached_dlight && surface->lightmapinfo->samples)
2374 R_BuildLightMap(ent, surface);
2375 // add face to draw list
2376 surfacelist[numsurfacelist++] = surface;
2377 counttriangles += surface->num_triangles;
2378 if (numsurfacelist >= maxsurfacelist)
2380 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2388 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2390 if (t != surface->texture)
2394 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2397 t = surface->texture;
2398 texture = t->currentframe;
2399 f = texture->currentmaterialflags & flagsmask;
2401 if (f && surface->num_triangles)
2403 // if lightmap parameters changed, rebuild lightmap texture
2404 if (surface->cached_dlight && surface->lightmapinfo->samples)
2405 R_BuildLightMap(ent, surface);
2406 // add face to draw list
2407 surfacelist[numsurfacelist++] = surface;
2408 counttriangles += surface->num_triangles;
2409 if (numsurfacelist >= maxsurfacelist)
2411 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2418 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2419 if (!r_showtrispass)
2420 renderstats.entities_triangles += counttriangles;