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 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 // FIXME: move this to client?
455 Cvar_RegisterVariable(&r_showtris);
456 Cvar_RegisterVariable(&r_showtris_polygonoffset);
457 Cvar_RegisterVariable(&r_shownormals);
458 Cvar_RegisterVariable(&r_showlighting);
459 Cvar_RegisterVariable(&r_showshadowvolumes);
460 Cvar_RegisterVariable(&r_showcollisionbrushes);
461 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
462 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
463 Cvar_RegisterVariable(&r_showdisabledepthtest);
464 Cvar_RegisterVariable(&r_drawentities);
465 Cvar_RegisterVariable(&r_drawviewmodel);
466 Cvar_RegisterVariable(&r_speeds);
467 Cvar_RegisterVariable(&r_fullbrights);
468 Cvar_RegisterVariable(&r_wateralpha);
469 Cvar_RegisterVariable(&r_dynamic);
470 Cvar_RegisterVariable(&r_fullbright);
471 Cvar_RegisterVariable(&r_textureunits);
472 Cvar_RegisterVariable(&r_lerpsprites);
473 Cvar_RegisterVariable(&r_lerpmodels);
474 Cvar_RegisterVariable(&r_waterscroll);
475 Cvar_RegisterVariable(&r_bloom);
476 Cvar_RegisterVariable(&r_bloom_intensity);
477 Cvar_RegisterVariable(&r_bloom_blur);
478 Cvar_RegisterVariable(&r_bloom_resolution);
479 Cvar_RegisterVariable(&r_bloom_power);
480 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
481 Cvar_RegisterVariable(&developer_texturelogging);
482 Cvar_RegisterVariable(&gl_lightmaps);
483 Cvar_RegisterVariable(&r_test);
484 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
485 Cvar_SetValue("r_fullbrights", 0);
486 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
489 static vec3_t r_farclip_origin;
490 static vec3_t r_farclip_direction;
491 static vec_t r_farclip_directiondist;
492 static vec_t r_farclip_meshfarclip;
493 static int r_farclip_directionbit0;
494 static int r_farclip_directionbit1;
495 static int r_farclip_directionbit2;
497 // enlarge farclip to accomodate box
498 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
501 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
502 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
503 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
504 if (r_farclip_meshfarclip < d)
505 r_farclip_meshfarclip = d;
508 // return farclip value
509 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
513 VectorCopy(origin, r_farclip_origin);
514 VectorCopy(direction, r_farclip_direction);
515 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
516 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
517 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
518 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
519 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
521 if (r_refdef.worldmodel)
522 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
523 for (i = 0;i < r_refdef.numentities;i++)
524 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
526 return r_farclip_meshfarclip - r_farclip_directiondist;
529 extern void R_Textures_Init(void);
530 extern void GL_Draw_Init(void);
531 extern void GL_Main_Init(void);
532 extern void R_Shadow_Init(void);
533 extern void R_Sky_Init(void);
534 extern void GL_Surf_Init(void);
535 extern void R_Crosshairs_Init(void);
536 extern void R_Light_Init(void);
537 extern void R_Particles_Init(void);
538 extern void R_Explosion_Init(void);
539 extern void gl_backend_init(void);
540 extern void Sbar_Init(void);
541 extern void R_LightningBeams_Init(void);
542 extern void Mod_RenderInit(void);
544 void Render_Init(void)
560 R_LightningBeams_Init();
569 extern char *ENGINE_EXTENSIONS;
572 VID_CheckExtensions();
574 // LordHavoc: report supported extensions
575 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
577 // clear to black (loading plaque will be seen over this)
578 qglClearColor(0,0,0,1);
579 qglClear(GL_COLOR_BUFFER_BIT);
582 int R_CullBox(const vec3_t mins, const vec3_t maxs)
586 for (i = 0;i < 4;i++)
593 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
597 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
601 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
605 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
609 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
613 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
617 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
621 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
629 //==================================================================================
631 static void R_MarkEntities (void)
634 entity_render_t *ent;
636 if (!r_drawentities.integer)
639 r_refdef.worldentity->visframe = r_framecount;
640 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
641 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
643 // worldmodel can check visibility
644 for (i = 0;i < r_refdef.numentities;i++)
646 ent = r_refdef.entities[i];
647 // some of the renderer still relies on origin...
648 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
649 // some of the renderer still relies on scale...
650 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
651 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)))
653 R_UpdateEntLights(ent);
654 ent->visframe = r_framecount;
660 // no worldmodel or it can't check visibility
661 for (i = 0;i < r_refdef.numentities;i++)
663 ent = r_refdef.entities[i];
664 // some of the renderer still relies on origin...
665 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
666 // some of the renderer still relies on scale...
667 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
668 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
670 R_UpdateEntLights(ent);
671 ent->visframe = r_framecount;
677 // only used if skyrendermasked, and normally returns false
678 int R_DrawBrushModelsSky (void)
681 entity_render_t *ent;
683 if (!r_drawentities.integer)
687 for (i = 0;i < r_refdef.numentities;i++)
689 ent = r_refdef.entities[i];
690 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
692 ent->model->DrawSky(ent);
699 void R_DrawNoModel(entity_render_t *ent);
700 void R_DrawModels(void)
703 entity_render_t *ent;
705 if (!r_drawentities.integer)
708 for (i = 0;i < r_refdef.numentities;i++)
710 ent = r_refdef.entities[i];
711 if (ent->visframe == r_framecount)
713 renderstats.entities++;
714 if (ent->model && ent->model->Draw != NULL)
715 ent->model->Draw(ent);
722 static void R_SetFrustum(void)
724 // break apart the view matrix into vectors for various purposes
725 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
726 VectorNegate(r_viewleft, r_viewright);
729 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
730 frustum[0].normal[1] = 0 - 0;
731 frustum[0].normal[2] = -1 - 0;
732 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
733 frustum[1].normal[1] = 0 + 0;
734 frustum[1].normal[2] = -1 + 0;
735 frustum[2].normal[0] = 0 - 0;
736 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
737 frustum[2].normal[2] = -1 - 0;
738 frustum[3].normal[0] = 0 + 0;
739 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
740 frustum[3].normal[2] = -1 + 0;
745 nudge = 1.0 - 1.0 / (1<<23);
746 frustum[4].normal[0] = 0 - 0;
747 frustum[4].normal[1] = 0 - 0;
748 frustum[4].normal[2] = -1 - -nudge;
749 frustum[4].dist = 0 - -2 * zNear * nudge;
750 frustum[5].normal[0] = 0 + 0;
751 frustum[5].normal[1] = 0 + 0;
752 frustum[5].normal[2] = -1 + -nudge;
753 frustum[5].dist = 0 + -2 * zNear * nudge;
759 frustum[0].normal[0] = m[3] - m[0];
760 frustum[0].normal[1] = m[7] - m[4];
761 frustum[0].normal[2] = m[11] - m[8];
762 frustum[0].dist = m[15] - m[12];
764 frustum[1].normal[0] = m[3] + m[0];
765 frustum[1].normal[1] = m[7] + m[4];
766 frustum[1].normal[2] = m[11] + m[8];
767 frustum[1].dist = m[15] + m[12];
769 frustum[2].normal[0] = m[3] - m[1];
770 frustum[2].normal[1] = m[7] - m[5];
771 frustum[2].normal[2] = m[11] - m[9];
772 frustum[2].dist = m[15] - m[13];
774 frustum[3].normal[0] = m[3] + m[1];
775 frustum[3].normal[1] = m[7] + m[5];
776 frustum[3].normal[2] = m[11] + m[9];
777 frustum[3].dist = m[15] + m[13];
779 frustum[4].normal[0] = m[3] - m[2];
780 frustum[4].normal[1] = m[7] - m[6];
781 frustum[4].normal[2] = m[11] - m[10];
782 frustum[4].dist = m[15] - m[14];
784 frustum[5].normal[0] = m[3] + m[2];
785 frustum[5].normal[1] = m[7] + m[6];
786 frustum[5].normal[2] = m[11] + m[10];
787 frustum[5].dist = m[15] + m[14];
792 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
793 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
794 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
795 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
796 VectorCopy(r_viewforward, frustum[4].normal);
797 VectorNormalize(frustum[0].normal);
798 VectorNormalize(frustum[1].normal);
799 VectorNormalize(frustum[2].normal);
800 VectorNormalize(frustum[3].normal);
801 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
802 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
803 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
804 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
805 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
806 PlaneClassify(&frustum[0]);
807 PlaneClassify(&frustum[1]);
808 PlaneClassify(&frustum[2]);
809 PlaneClassify(&frustum[3]);
810 PlaneClassify(&frustum[4]);
812 // LordHavoc: note to all quake engine coders, Quake had a special case
813 // for 90 degrees which assumed a square view (wrong), so I removed it,
814 // Quake2 has it disabled as well.
816 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
817 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
818 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
819 //PlaneClassify(&frustum[0]);
821 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
822 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
823 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
824 //PlaneClassify(&frustum[1]);
826 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
827 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
828 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
829 //PlaneClassify(&frustum[2]);
831 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
832 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
833 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
834 //PlaneClassify(&frustum[3]);
837 //VectorCopy(r_viewforward, frustum[4].normal);
838 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
839 //PlaneClassify(&frustum[4]);
842 static void R_BlendView(void)
844 int screenwidth, screenheight;
849 // set the (poorly named) screenwidth and screenheight variables to
850 // a power of 2 at least as large as the screen, these will define the
851 // size of the texture to allocate
852 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
853 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
855 doblend = r_refdef.viewblend[3] >= 0.01f;
856 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;
858 if (!dobloom && !doblend)
861 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
864 R_Mesh_Matrix(&identitymatrix);
865 // vertex coordinates for a quad that covers the screen exactly
866 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
867 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
868 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
869 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
872 int bloomwidth, bloomheight, x, dobloomblend, range;
873 float xoffset, yoffset, r;
875 // allocate textures as needed
876 if (!r_bloom_texture_screen)
877 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
878 if (!r_bloom_texture_bloom)
879 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
880 // set bloomwidth and bloomheight to the bloom resolution that will be
881 // used (often less than the screen resolution for faster rendering)
882 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
883 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
884 // set up a texcoord array for the full resolution screen image
885 // (we have to keep this around to copy back during final render)
886 varray_texcoord2f[0][0] = 0;
887 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
888 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
889 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
890 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
891 varray_texcoord2f[0][5] = 0;
892 varray_texcoord2f[0][6] = 0;
893 varray_texcoord2f[0][7] = 0;
894 // set up a texcoord array for the reduced resolution bloom image
895 // (which will be additive blended over the screen image)
896 varray_texcoord2f[1][0] = 0;
897 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
898 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
899 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
900 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
901 varray_texcoord2f[1][5] = 0;
902 varray_texcoord2f[1][6] = 0;
903 varray_texcoord2f[1][7] = 0;
904 memset(&m, 0, sizeof(m));
905 m.pointer_vertex = varray_vertex3f;
906 m.pointer_texcoord[0] = varray_texcoord2f[0];
907 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
909 // copy view into the full resolution screen image texture
911 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
912 renderstats.bloom_copypixels += r_view_width * r_view_height;
913 // now scale it down to the bloom size and raise to a power of itself
914 // to darken it (this leaves the really bright stuff bright, and
915 // everything else becomes very dark)
916 // TODO: optimize with multitexture or GLSL
917 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
918 GL_BlendFunc(GL_ONE, GL_ZERO);
919 GL_Color(1, 1, 1, 1);
920 R_Mesh_Draw(0, 4, 2, polygonelements);
921 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
922 // render multiple times with a multiply blendfunc to raise to a power
923 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
924 for (x = 1;x < r_bloom_power.integer;x++)
926 R_Mesh_Draw(0, 4, 2, polygonelements);
927 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
929 // we now have a darkened bloom image in the framebuffer, copy it into
930 // the bloom image texture for more processing
931 memset(&m, 0, sizeof(m));
932 m.pointer_vertex = varray_vertex3f;
933 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
934 m.pointer_texcoord[0] = varray_texcoord2f[2];
937 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
938 renderstats.bloom_copypixels += bloomwidth * bloomheight;
939 // blend on at multiple vertical offsets to achieve a vertical blur
940 // TODO: do offset blends using GLSL
941 range = r_bloom_blur.integer * bloomwidth / 320;
942 GL_BlendFunc(GL_ONE, GL_ZERO);
943 for (x = -range;x <= range;x++)
945 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
946 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
947 // compute a texcoord array with the specified x and y offset
948 varray_texcoord2f[2][0] = xoffset+0;
949 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
950 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
951 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
952 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
953 varray_texcoord2f[2][5] = yoffset+0;
954 varray_texcoord2f[2][6] = xoffset+0;
955 varray_texcoord2f[2][7] = yoffset+0;
956 // this r value looks like a 'dot' particle, fading sharply to
957 // black at the edges
958 // (probably not realistic but looks good enough)
959 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
962 GL_Color(r, r, r, 1);
963 R_Mesh_Draw(0, 4, 2, polygonelements);
964 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
965 GL_BlendFunc(GL_ONE, GL_ONE);
967 // copy the vertically blurred bloom view to a texture
969 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
970 renderstats.bloom_copypixels += bloomwidth * bloomheight;
971 // blend the vertically blurred image at multiple offsets horizontally
972 // to finish the blur effect
973 // TODO: do offset blends using GLSL
974 range = r_bloom_blur.integer * bloomwidth / 320;
975 GL_BlendFunc(GL_ONE, GL_ZERO);
976 for (x = -range;x <= range;x++)
978 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
979 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
980 // compute a texcoord array with the specified x and y offset
981 varray_texcoord2f[2][0] = xoffset+0;
982 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
983 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
984 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
985 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
986 varray_texcoord2f[2][5] = yoffset+0;
987 varray_texcoord2f[2][6] = xoffset+0;
988 varray_texcoord2f[2][7] = yoffset+0;
989 // this r value looks like a 'dot' particle, fading sharply to
990 // black at the edges
991 // (probably not realistic but looks good enough)
992 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
995 GL_Color(r, r, r, 1);
996 R_Mesh_Draw(0, 4, 2, polygonelements);
997 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
998 GL_BlendFunc(GL_ONE, GL_ONE);
1000 // copy the blurred bloom view to a texture
1001 GL_ActiveTexture(0);
1002 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1003 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1004 // go back to full view area
1005 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1006 // put the original screen image back in place and blend the bloom
1008 memset(&m, 0, sizeof(m));
1009 m.pointer_vertex = varray_vertex3f;
1010 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1011 m.pointer_texcoord[0] = varray_texcoord2f[0];
1013 dobloomblend = false;
1015 // do both in one pass if possible
1016 if (r_textureunits.integer >= 2 && gl_combine.integer)
1018 dobloomblend = false;
1019 m.texcombinergb[1] = GL_ADD;
1020 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1021 m.pointer_texcoord[1] = varray_texcoord2f[1];
1024 dobloomblend = true;
1027 GL_BlendFunc(GL_ONE, GL_ZERO);
1029 R_Mesh_Draw(0, 4, 2, polygonelements);
1030 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1031 // now blend on the bloom texture if multipass
1034 memset(&m, 0, sizeof(m));
1035 m.pointer_vertex = varray_vertex3f;
1036 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1037 m.pointer_texcoord[0] = varray_texcoord2f[1];
1039 GL_BlendFunc(GL_ONE, GL_ONE);
1041 R_Mesh_Draw(0, 4, 2, polygonelements);
1042 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1047 // apply a color tint to the whole view
1048 memset(&m, 0, sizeof(m));
1049 m.pointer_vertex = varray_vertex3f;
1051 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1052 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1053 R_Mesh_Draw(0, 4, 2, polygonelements);
1057 void R_RenderScene(void);
1059 matrix4x4_t r_waterscrollmatrix;
1066 void R_RenderView(void)
1068 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1069 return; //Host_Error ("R_RenderView: NULL worldmodel");
1071 r_view_width = bound(0, r_refdef.width, vid.width);
1072 r_view_height = bound(0, r_refdef.height, vid.height);
1074 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1075 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1077 r_view_matrix = r_refdef.viewentitymatrix;
1078 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1079 r_rtworld = r_shadow_realtime_world.integer;
1080 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1081 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1082 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1083 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1085 // GL is weird because it's bottom to top, r_view_y is top to bottom
1086 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1087 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1088 GL_ScissorTest(true);
1093 if (r_timereport_active)
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 if (r_timereport_active)
1107 R_TimeReport("blendview");
1109 GL_Scissor(0, 0, vid.width, vid.height);
1110 GL_ScissorTest(false);
1114 void CSQC_R_ClearScreen (void)
1116 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1117 return; //Host_Error ("R_RenderView: NULL worldmodel");
1119 r_view_width = bound(0, r_refdef.width, vid.width);
1120 r_view_height = bound(0, r_refdef.height, vid.height);
1122 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1123 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1125 r_view_matrix = r_refdef.viewentitymatrix;
1126 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1127 r_rtworld = r_shadow_realtime_world.integer;
1128 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1129 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1130 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1131 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1133 // GL is weird because it's bottom to top, r_view_y is top to bottom
1134 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1135 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1136 GL_ScissorTest(true);
1141 if (r_timereport_active)
1142 R_TimeReport("setup");
1146 void CSQC_R_RenderScene (void)
1148 qglDepthFunc(GL_LEQUAL);
1149 qglPolygonOffset(0, 0);
1150 qglEnable(GL_POLYGON_OFFSET_FILL);
1154 qglPolygonOffset(0, 0);
1155 qglDisable(GL_POLYGON_OFFSET_FILL);
1158 if (r_timereport_active)
1159 R_TimeReport("blendview");
1161 GL_Scissor(0, 0, vid.width, vid.height);
1162 GL_ScissorTest(false);
1165 extern void R_DrawLightningBeams (void);
1166 extern void VM_AddPolygonsToMeshQueue (void);
1167 void R_RenderScene(void)
1169 // don't let sound skip if going slow
1170 if (r_refdef.extraupdate)
1175 R_MeshQueue_BeginScene();
1179 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1180 if (r_rtworldshadows || r_rtdlightshadows)
1181 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f);
1183 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f, r_farclip);
1185 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1187 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);
1191 R_WorldVisibility();
1192 if (r_timereport_active)
1193 R_TimeReport("worldvis");
1196 if (r_timereport_active)
1197 R_TimeReport("markentity");
1199 R_Shadow_UpdateWorldLightSelection();
1201 for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1207 GL_BlendFunc(GL_ONE, GL_ONE);
1208 GL_DepthTest(!r_showdisabledepthtest.integer);
1209 GL_DepthMask(GL_FALSE);
1210 memset(&m, 0, sizeof(m));
1212 //qglEnable(GL_LINE_SMOOTH);
1213 qglEnable(GL_POLYGON_OFFSET_LINE);
1214 qglPolygonOffset(0, r_showtris_polygonoffset.value);
1218 if (cl.csqc_vidvars.drawworld)
1220 // don't let sound skip if going slow
1221 if (r_refdef.extraupdate)
1225 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1226 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1228 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1229 if (r_timereport_active)
1230 R_TimeReport("worldsky");
1233 if (R_DrawBrushModelsSky() && r_timereport_active)
1234 R_TimeReport("bmodelsky");
1237 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1238 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1240 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1241 if (r_timereport_active)
1242 R_TimeReport("world");
1246 // don't let sound skip if going slow
1247 if (r_refdef.extraupdate)
1251 GL_ShowTrisColor(0, 0.015, 0, 1);
1254 if (r_timereport_active)
1255 R_TimeReport("models");
1257 // don't let sound skip if going slow
1258 if (r_refdef.extraupdate)
1262 GL_ShowTrisColor(0, 0, 0.033, 1);
1263 R_ShadowVolumeLighting(false);
1264 if (r_timereport_active)
1265 R_TimeReport("rtlights");
1267 // don't let sound skip if going slow
1268 if (r_refdef.extraupdate)
1272 GL_ShowTrisColor(0.1, 0, 0, 1);
1274 if (cl.csqc_vidvars.drawworld)
1276 R_DrawLightningBeams();
1277 if (r_timereport_active)
1278 R_TimeReport("lightning");
1281 if (r_timereport_active)
1282 R_TimeReport("particles");
1285 if (r_timereport_active)
1286 R_TimeReport("explosions");
1289 R_MeshQueue_RenderTransparent();
1290 if (r_timereport_active)
1291 R_TimeReport("drawtrans");
1293 if (cl.csqc_vidvars.drawworld)
1296 if (r_timereport_active)
1297 R_TimeReport("coronas");
1299 if(cl.csqc_vidvars.drawcrosshair)
1301 R_DrawWorldCrosshair();
1302 if (r_timereport_active)
1303 R_TimeReport("crosshair");
1306 VM_AddPolygonsToMeshQueue();
1308 R_MeshQueue_Render();
1312 //qglDisable(GL_LINE_SMOOTH);
1313 qglDisable(GL_POLYGON_OFFSET_LINE);
1319 R_MeshQueue_EndScene();
1321 // don't let sound skip if going slow
1322 if (r_refdef.extraupdate)
1327 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1330 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1332 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1333 GL_DepthMask(false);
1335 R_Mesh_Matrix(&identitymatrix);
1337 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1338 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1339 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1340 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1341 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1342 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1343 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1344 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1345 R_FillColors(color, 8, cr, cg, cb, ca);
1348 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1350 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1352 c[0] = c[0] * f1 + fogcolor[0] * f2;
1353 c[1] = c[1] * f1 + fogcolor[1] * f2;
1354 c[2] = c[2] * f1 + fogcolor[2] * f2;
1357 memset(&m, 0, sizeof(m));
1358 m.pointer_vertex = vertex3f;
1359 m.pointer_color = color;
1365 int nomodelelements[24] =
1377 float nomodelvertex3f[6*3] =
1387 float nomodelcolor4f[6*4] =
1389 0.0f, 0.0f, 0.5f, 1.0f,
1390 0.0f, 0.0f, 0.5f, 1.0f,
1391 0.0f, 0.5f, 0.0f, 1.0f,
1392 0.0f, 0.5f, 0.0f, 1.0f,
1393 0.5f, 0.0f, 0.0f, 1.0f,
1394 0.5f, 0.0f, 0.0f, 1.0f
1397 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
1403 R_Mesh_Matrix(&ent->matrix);
1405 memset(&m, 0, sizeof(m));
1406 m.pointer_vertex = nomodelvertex3f;
1408 if (ent->flags & EF_ADDITIVE)
1410 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1411 GL_DepthMask(false);
1413 else if (ent->alpha < 1)
1415 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1416 GL_DepthMask(false);
1420 GL_BlendFunc(GL_ONE, GL_ZERO);
1423 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1426 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1427 m.pointer_color = color4f;
1428 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1430 for (i = 0, c = color4f;i < 6;i++, c += 4)
1432 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1433 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1434 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1438 else if (ent->alpha != 1)
1440 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1441 m.pointer_color = color4f;
1442 for (i = 0, c = color4f;i < 6;i++, c += 4)
1446 m.pointer_color = nomodelcolor4f;
1448 R_Mesh_Draw(0, 6, 8, nomodelelements);
1451 void R_DrawNoModel(entity_render_t *ent)
1453 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1454 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1456 // R_DrawNoModelCallback(ent, 0);
1459 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1461 vec3_t right1, right2, diff, normal;
1463 VectorSubtract (org2, org1, normal);
1465 // calculate 'right' vector for start
1466 VectorSubtract (r_vieworigin, org1, diff);
1467 CrossProduct (normal, diff, right1);
1468 VectorNormalize (right1);
1470 // calculate 'right' vector for end
1471 VectorSubtract (r_vieworigin, org2, diff);
1472 CrossProduct (normal, diff, right2);
1473 VectorNormalize (right2);
1475 vert[ 0] = org1[0] + width * right1[0];
1476 vert[ 1] = org1[1] + width * right1[1];
1477 vert[ 2] = org1[2] + width * right1[2];
1478 vert[ 3] = org1[0] - width * right1[0];
1479 vert[ 4] = org1[1] - width * right1[1];
1480 vert[ 5] = org1[2] - width * right1[2];
1481 vert[ 6] = org2[0] - width * right2[0];
1482 vert[ 7] = org2[1] - width * right2[1];
1483 vert[ 8] = org2[2] - width * right2[2];
1484 vert[ 9] = org2[0] + width * right2[0];
1485 vert[10] = org2[1] + width * right2[1];
1486 vert[11] = org2[2] + width * right2[2];
1489 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1491 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)
1493 float fog = 0.0f, ifog;
1497 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1500 R_Mesh_Matrix(&identitymatrix);
1501 GL_BlendFunc(blendfunc1, blendfunc2);
1502 GL_DepthMask(false);
1503 GL_DepthTest(!depthdisable);
1505 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1506 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1507 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1508 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1509 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1510 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1511 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1512 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1513 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1514 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1515 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1516 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1518 memset(&m, 0, sizeof(m));
1519 m.tex[0] = R_GetTexture(texture);
1520 m.pointer_texcoord[0] = spritetexcoord2f;
1521 m.pointer_vertex = varray_vertex3f;
1523 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
1524 R_Mesh_Draw(0, 4, 2, polygonelements);
1526 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
1528 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
1529 GL_BlendFunc(blendfunc1, GL_ONE);
1530 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
1531 R_Mesh_Draw(0, 4, 2, polygonelements);
1535 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1539 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1540 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1542 if (i == mesh->numvertices)
1544 if (mesh->numvertices < mesh->maxvertices)
1546 VectorCopy(v, vertex3f);
1547 mesh->numvertices++;
1549 return mesh->numvertices;
1555 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1559 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1560 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1561 e = mesh->element3i + mesh->numtriangles * 3;
1562 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1564 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1565 if (mesh->numtriangles < mesh->maxtriangles)
1570 mesh->numtriangles++;
1572 element[1] = element[2];
1576 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1578 int planenum, planenum2;
1581 mplane_t *plane, *plane2;
1582 float temppoints[2][256*3];
1583 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1587 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1588 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1590 if (planenum2 == planenum)
1592 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, NULL);
1595 if (tempnumpoints < 3)
1597 // generate elements forming a triangle fan for this polygon
1598 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1602 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)
1604 texturelayer_t *layer;
1605 layer = t->currentlayers + t->currentnumlayers++;
1607 layer->depthmask = depthmask;
1608 layer->blendfunc1 = blendfunc1;
1609 layer->blendfunc2 = blendfunc2;
1610 layer->texture = texture;
1611 layer->texmatrix = *matrix;
1612 layer->color[0] = r;
1613 layer->color[1] = g;
1614 layer->color[2] = b;
1615 layer->color[3] = a;
1618 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1620 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1621 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1624 texture_t *texture = t;
1625 model_t *model = ent->model;
1626 int s = ent->skinnum;
1627 if ((unsigned int)s >= (unsigned int)model->numskins)
1629 if (model->skinscenes)
1631 if (model->skinscenes[s].framecount > 1)
1632 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1634 s = model->skinscenes[s].firstframe;
1637 t = t + s * model->num_surfaces;
1639 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];
1640 texture->currentframe = t;
1643 t->currentmaterialflags = t->basematerialflags;
1644 t->currentalpha = ent->alpha;
1645 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1646 t->currentalpha *= r_wateralpha.value;
1647 if (!(ent->flags & RENDER_LIGHT))
1648 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1649 if (ent->effects & EF_ADDITIVE)
1650 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1651 else if (t->currentalpha < 1)
1652 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1653 if (ent->effects & EF_NODEPTHTEST)
1654 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1655 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1656 t->currenttexmatrix = r_waterscrollmatrix;
1658 t->currenttexmatrix = identitymatrix;
1659 t->currentnumlayers = 0;
1660 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1662 if (gl_lightmaps.integer)
1663 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
1664 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1666 // transparent sky would be ridiculous
1667 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1668 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1672 int blendfunc1, blendfunc2, depthmask;
1673 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1675 blendfunc1 = GL_SRC_ALPHA;
1676 blendfunc2 = GL_ONE;
1679 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1681 blendfunc1 = GL_SRC_ALPHA;
1682 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1687 blendfunc1 = GL_ONE;
1688 blendfunc2 = GL_ZERO;
1691 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1693 rtexture_t *currentbasetexture;
1695 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1696 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1697 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
1698 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1700 // fullbright is not affected by r_lightmapintensity
1701 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
1702 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1703 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);
1704 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1705 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);
1711 // q3bsp has no lightmap updates, so the lightstylevalue that
1712 // would normally be baked into the lightmaptexture must be
1713 // applied to the color
1714 if (ent->model->type == mod_brushq3)
1715 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1716 colorscale *= r_lightmapintensity;
1717 if (r_textureunits.integer >= 2 && gl_combine.integer)
1718 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);
1719 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1720 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);
1722 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);
1723 if (r_ambient.value >= (1.0f/64.0f))
1724 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);
1725 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1727 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);
1728 if (r_ambient.value >= (1.0f/64.0f))
1729 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);
1731 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1733 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);
1734 if (r_ambient.value >= (1.0f/64.0f))
1735 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);
1738 if (t->skin.glow != NULL)
1739 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
1740 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1742 // if this is opaque use alpha blend which will darken the earlier
1745 // if this is an alpha blended material, all the earlier passes
1746 // were darkened by fog already, so we only need to add the fog
1747 // color ontop through the fog mask texture
1749 // if this is an additive blended material, all the earlier passes
1750 // were darkened by fog already, and we should not add fog color
1751 // (because the background was not darkened, there is no fog color
1752 // that was lost behind it).
1753 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], t->currentalpha);
1760 void R_UpdateAllTextureInfo(entity_render_t *ent)
1764 for (i = 0;i < ent->model->num_textures;i++)
1765 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1768 float *rsurface_vertex3f;
1769 float *rsurface_svector3f;
1770 float *rsurface_tvector3f;
1771 float *rsurface_normal3f;
1772 float *rsurface_lightmapcolor4f;
1774 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1777 float center[3], forward[3], right[3], up[3], v[4][3];
1778 matrix4x4_t matrix1, imatrix1;
1779 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1781 rsurface_vertex3f = varray_vertex3f;
1782 rsurface_svector3f = NULL;
1783 rsurface_tvector3f = NULL;
1784 rsurface_normal3f = NULL;
1785 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1789 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1790 rsurface_svector3f = surface->groupmesh->data_svector3f;
1791 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1792 rsurface_normal3f = surface->groupmesh->data_normal3f;
1794 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1796 if (!rsurface_svector3f)
1798 rsurface_svector3f = varray_svector3f;
1799 rsurface_tvector3f = varray_tvector3f;
1800 rsurface_normal3f = varray_normal3f;
1801 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);
1803 // a single autosprite surface can contain multiple sprites...
1804 VectorClear(forward);
1806 VectorSet(up, 0, 0, 1);
1807 for (j = 0;j < surface->num_vertices - 3;j += 4)
1809 VectorClear(center);
1810 for (i = 0;i < 4;i++)
1811 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1812 VectorScale(center, 0.25f, center);
1813 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1814 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);
1815 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1816 for (i = 0;i < 4;i++)
1817 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1818 forward[0] = modelorg[0] - center[0];
1819 forward[1] = modelorg[1] - center[1];
1820 VectorNormalize(forward);
1821 right[0] = forward[1];
1822 right[1] = -forward[0];
1823 for (i = 0;i < 4;i++)
1824 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1826 rsurface_vertex3f = varray_vertex3f;
1827 rsurface_svector3f = NULL;
1828 rsurface_tvector3f = NULL;
1829 rsurface_normal3f = NULL;
1831 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1833 if (!rsurface_svector3f)
1835 rsurface_svector3f = varray_svector3f;
1836 rsurface_tvector3f = varray_tvector3f;
1837 rsurface_normal3f = varray_normal3f;
1838 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);
1840 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1841 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1842 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1843 // a single autosprite surface can contain multiple sprites...
1844 for (j = 0;j < surface->num_vertices - 3;j += 4)
1846 VectorClear(center);
1847 for (i = 0;i < 4;i++)
1848 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1849 VectorScale(center, 0.25f, center);
1850 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1851 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);
1852 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1853 for (i = 0;i < 4;i++)
1854 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1855 for (i = 0;i < 4;i++)
1856 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1858 rsurface_vertex3f = varray_vertex3f;
1859 rsurface_svector3f = NULL;
1860 rsurface_tvector3f = NULL;
1861 rsurface_normal3f = NULL;
1863 R_Mesh_VertexPointer(rsurface_vertex3f);
1866 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)
1874 vec4_t ambientcolor4f;
1875 vec3_t diffusecolor;
1876 vec3_t diffusenormal;
1877 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1879 rsurface_lightmapcolor4f = varray_color4f;
1880 if (rsurface_normal3f == NULL)
1882 rsurface_normal3f = varray_normal3f;
1883 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);
1885 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);
1894 r = ambientcolor4f[0];
1895 g = ambientcolor4f[1];
1896 b = ambientcolor4f[2];
1897 a = ambientcolor4f[3];
1898 rsurface_lightmapcolor4f = NULL;
1901 else if (lightmode >= 1)
1903 if (surface->lightmapinfo)
1905 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1907 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1910 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1911 VectorScale(lm, scale, c);
1912 if (surface->lightmapinfo->styles[1] != 255)
1914 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1916 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1917 VectorMA(c, scale, lm, c);
1918 if (surface->lightmapinfo->styles[2] != 255)
1921 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1922 VectorMA(c, scale, lm, c);
1923 if (surface->lightmapinfo->styles[3] != 255)
1926 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1927 VectorMA(c, scale, lm, c);
1935 rsurface_lightmapcolor4f = varray_color4f;
1938 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1941 rsurface_lightmapcolor4f = NULL;
1944 if (rsurface_lightmapcolor4f)
1946 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)
1948 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1957 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)
1959 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1966 rsurface_lightmapcolor4f = varray_color4f;
1968 if (applycolor && rsurface_lightmapcolor4f)
1970 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)
1977 rsurface_lightmapcolor4f = varray_color4f;
1979 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1980 GL_Color(r, g, b, a);
1983 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1985 int texturesurfaceindex;
1987 const msurface_t *surface;
1988 qboolean applycolor;
1990 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1992 renderstats.entities_surfaces += texturenumsurfaces;
1993 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1994 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1995 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1996 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
1997 qglDisable(GL_CULL_FACE);
1998 if (texture->currentnumlayers)
2001 texturelayer_t *layer;
2002 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2005 int layertexrgbscale;
2006 GL_DepthMask(layer->depthmask);
2007 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2008 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2010 layertexrgbscale = 4;
2011 VectorScale(layer->color, 0.25f, layercolor);
2013 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2015 layertexrgbscale = 2;
2016 VectorScale(layer->color, 0.5f, layercolor);
2020 layertexrgbscale = 1;
2021 VectorScale(layer->color, 1.0f, layercolor);
2023 layercolor[3] = layer->color[3];
2024 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2025 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2026 switch (layer->type)
2028 case TEXTURELAYERTYPE_SKY:
2031 skyrendernow = false;
2032 if (skyrendermasked)
2035 // restore entity matrix and GL_Color
2036 R_Mesh_Matrix(&ent->matrix);
2037 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2040 // LordHavoc: HalfLife maps have freaky skypolys...
2041 //if (!ent->model->brush.ishlbsp)
2043 if (skyrendermasked)
2045 // depth-only (masking)
2046 GL_ColorMask(0,0,0,0);
2047 // just to make sure that braindead drivers don't draw anything
2048 // despite that colormask...
2049 GL_BlendFunc(GL_ZERO, GL_ONE);
2054 GL_BlendFunc(GL_ONE, GL_ZERO);
2056 memset(&m, 0, sizeof(m));
2058 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2060 surface = texturesurfacelist[texturesurfaceindex];
2061 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2062 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2063 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2064 GL_LockArrays(0, 0);
2066 if (skyrendermasked)
2067 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2070 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2071 memset(&m, 0, sizeof(m));
2072 m.tex[1] = R_GetTexture(layer->texture);
2073 m.texmatrix[1] = layer->texmatrix;
2074 m.texrgbscale[1] = layertexrgbscale;
2075 m.pointer_color = varray_color4f;
2077 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2079 surface = texturesurfacelist[texturesurfaceindex];
2080 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2081 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2082 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2085 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2086 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2088 else if (surface->lightmaptexture)
2090 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2091 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2095 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2096 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2098 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2099 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2100 GL_LockArrays(0, 0);
2103 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2104 memset(&m, 0, sizeof(m));
2105 m.tex[0] = R_GetTexture(layer->texture);
2106 m.texmatrix[0] = layer->texmatrix;
2107 m.pointer_color = varray_color4f;
2108 m.texrgbscale[0] = layertexrgbscale;
2110 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2112 surface = texturesurfacelist[texturesurfaceindex];
2113 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2114 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2117 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2118 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2120 else if (surface->lightmaptexture)
2122 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2123 R_Mesh_ColorPointer(NULL);
2127 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2128 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2130 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2131 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2132 GL_LockArrays(0, 0);
2134 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2135 memset(&m, 0, sizeof(m));
2136 m.tex[0] = R_GetTexture(layer->texture);
2137 m.texmatrix[0] = layer->texmatrix;
2138 m.pointer_color = varray_color4f;
2139 m.texrgbscale[0] = layertexrgbscale;
2141 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2143 surface = texturesurfacelist[texturesurfaceindex];
2144 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2145 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2146 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2147 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2148 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2149 GL_LockArrays(0, 0);
2152 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2153 memset(&m, 0, sizeof(m));
2154 m.tex[0] = R_GetTexture(layer->texture);
2155 m.texmatrix[0] = layer->texmatrix;
2156 m.texrgbscale[0] = layertexrgbscale;
2157 m.pointer_color = varray_color4f;
2159 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2161 surface = texturesurfacelist[texturesurfaceindex];
2162 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2163 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2164 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2165 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2166 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2167 GL_LockArrays(0, 0);
2170 case TEXTURELAYERTYPE_TEXTURE:
2171 memset(&m, 0, sizeof(m));
2172 m.tex[0] = R_GetTexture(layer->texture);
2173 m.texmatrix[0] = layer->texmatrix;
2174 m.pointer_color = varray_color4f;
2175 m.texrgbscale[0] = layertexrgbscale;
2177 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2179 surface = texturesurfacelist[texturesurfaceindex];
2180 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2181 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2182 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2183 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2184 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2185 GL_LockArrays(0, 0);
2188 case TEXTURELAYERTYPE_FOG:
2189 memset(&m, 0, sizeof(m));
2192 m.tex[0] = R_GetTexture(layer->texture);
2193 m.texmatrix[0] = layer->texmatrix;
2196 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2200 surface = texturesurfacelist[texturesurfaceindex];
2201 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2203 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2204 R_Mesh_ColorPointer(varray_color4f);
2205 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)
2207 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2208 c[0] = layercolor[0];
2209 c[1] = layercolor[1];
2210 c[2] = layercolor[2];
2211 c[3] = f * layercolor[3];
2213 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2214 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2215 GL_LockArrays(0, 0);
2219 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2221 // if trying to do overbright on first pass of an opaque surface
2222 // when combine is not supported, brighten as a post process
2223 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2226 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2227 GL_Color(1, 1, 1, 1);
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 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2235 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2236 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2237 GL_LockArrays(0, 0);
2241 if (r_shownormals.integer && !r_showtrispass)
2245 GL_DepthTest(!r_showdisabledepthtest.integer);
2246 GL_DepthMask(texture->currentlayers->depthmask);
2247 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
2248 memset(&m, 0, sizeof(m));
2250 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2252 surface = texturesurfacelist[texturesurfaceindex];
2253 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2254 if (!rsurface_svector3f)
2256 rsurface_svector3f = varray_svector3f;
2257 rsurface_tvector3f = varray_tvector3f;
2258 rsurface_normal3f = varray_normal3f;
2259 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);
2261 GL_Color(1, 0, 0, 1);
2263 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2265 VectorCopy(rsurface_vertex3f + k * 3, v);
2266 qglVertex3f(v[0], v[1], v[2]);
2267 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
2268 qglVertex3f(v[0], v[1], v[2]);
2270 GL_Color(0, 0, 1, 1);
2271 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2273 VectorCopy(rsurface_vertex3f + k * 3, v);
2274 qglVertex3f(v[0], v[1], v[2]);
2275 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
2276 qglVertex3f(v[0], v[1], v[2]);
2278 GL_Color(0, 1, 0, 1);
2279 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2281 VectorCopy(rsurface_vertex3f + k * 3, v);
2282 qglVertex3f(v[0], v[1], v[2]);
2283 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
2284 qglVertex3f(v[0], v[1], v[2]);
2290 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2291 qglEnable(GL_CULL_FACE);
2294 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2296 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
2300 texture = surface->texture;
2301 if (texture->basematerialflags & MATERIALFLAG_SKY)
2302 return; // transparent sky is too difficult
2303 R_UpdateTextureInfo(ent, texture);
2305 R_Mesh_Matrix(&ent->matrix);
2306 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2307 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2310 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2312 int texturesurfaceindex;
2313 const msurface_t *surface;
2314 vec3_t tempcenter, center;
2315 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2317 // drawing sky transparently would be too difficult
2318 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2320 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2322 surface = texturesurfacelist[texturesurfaceindex];
2323 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2324 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2325 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2326 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2327 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
2332 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2335 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2336 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2338 int i, j, f, flagsmask;
2339 int counttriangles = 0;
2340 msurface_t *surface, **surfacechain;
2341 texture_t *t, *texture;
2342 model_t *model = ent->model;
2344 const int maxsurfacelist = 1024;
2345 int numsurfacelist = 0;
2346 const msurface_t *surfacelist[1024];
2349 R_Mesh_Matrix(&ent->matrix);
2350 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2352 // update light styles
2353 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2355 for (i = 0;i < model->brushq1.light_styles;i++)
2357 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2359 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2360 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2361 for (;(surface = *surfacechain);surfacechain++)
2362 surface->cached_dlight = true;
2367 R_UpdateAllTextureInfo(ent);
2368 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2373 if (ent == r_refdef.worldentity)
2375 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2377 if (!r_worldsurfacevisible[j])
2379 if (t != surface->texture)
2383 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2386 t = surface->texture;
2387 texture = t->currentframe;
2388 f = texture->currentmaterialflags & flagsmask;
2390 if (f && surface->num_triangles)
2392 // if lightmap parameters changed, rebuild lightmap texture
2393 if (surface->cached_dlight && surface->lightmapinfo->samples)
2394 R_BuildLightMap(ent, surface);
2395 // add face to draw list
2396 surfacelist[numsurfacelist++] = surface;
2397 counttriangles += surface->num_triangles;
2398 if (numsurfacelist >= maxsurfacelist)
2400 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2408 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2410 if (t != surface->texture)
2414 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2417 t = surface->texture;
2418 texture = t->currentframe;
2419 f = texture->currentmaterialflags & flagsmask;
2421 if (f && surface->num_triangles)
2423 // if lightmap parameters changed, rebuild lightmap texture
2424 if (surface->cached_dlight && surface->lightmapinfo->samples)
2425 R_BuildLightMap(ent, surface);
2426 // add face to draw list
2427 surfacelist[numsurfacelist++] = surface;
2428 counttriangles += surface->num_triangles;
2429 if (numsurfacelist >= maxsurfacelist)
2431 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2438 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2439 if (!r_showtrispass)
2440 renderstats.entities_triangles += counttriangles;