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 renderstats_t renderstats;
33 // true during envmap command capture
36 // maximum visible distance (recalculated from world box each frame)
38 // brightness of world lightmaps and related lighting
39 // (often reduced when world rtlights are enabled)
40 float r_lightmapintensity;
41 // whether to draw world lights realtime, dlights realtime, and their shadows
43 qboolean r_rtworldshadows;
45 qboolean r_rtdlightshadows;
48 // forces all rendering to draw triangle outlines
63 matrix4x4_t r_view_matrix;
70 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
71 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
72 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"};
73 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
74 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"};
75 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"};
76 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
77 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"};
78 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"};
79 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"};
80 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
81 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
82 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
83 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
84 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
85 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
86 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
89 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
90 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
91 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
92 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
93 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
94 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
96 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)"};
98 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
99 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
100 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
102 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
103 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
104 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
105 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
106 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
108 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"};
110 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"};
112 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
114 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
116 rtexturepool_t *r_main_texturepool;
117 rtexture_t *r_bloom_texture_screen;
118 rtexture_t *r_bloom_texture_bloom;
119 rtexture_t *r_texture_blanknormalmap;
120 rtexture_t *r_texture_white;
121 rtexture_t *r_texture_black;
122 rtexture_t *r_texture_notexture;
123 rtexture_t *r_texture_whitecube;
124 rtexture_t *r_texture_normalizationcube;
125 rtexture_t *r_texture_fogattenuation;
126 rtexture_t *r_texture_fogintensity;
128 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
131 for (i = 0;i < verts;i++)
142 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
145 for (i = 0;i < verts;i++)
160 vec_t fogtabledistmultiplier;
161 float fogtable[FOGTABLEWIDTH];
162 float fog_density, fog_red, fog_green, fog_blue;
164 qboolean oldgl_fogenable;
165 void R_UpdateFog(void)
167 if (gamemode == GAME_NEHAHRA)
169 if (gl_fogenable.integer)
171 oldgl_fogenable = true;
172 fog_density = gl_fogdensity.value;
173 fog_red = gl_fogred.value;
174 fog_green = gl_foggreen.value;
175 fog_blue = gl_fogblue.value;
177 else if (oldgl_fogenable)
179 oldgl_fogenable = false;
188 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
189 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
190 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
195 fogdensity = -4000.0f / (fog_density * fog_density);
196 // this is the point where the fog reaches 0.9986 alpha, which we
197 // consider a good enough cutoff point for the texture
198 // (0.9986 * 256 == 255.6)
199 fogrange = 400 / fog_density;
200 fograngerecip = 1.0f / fogrange;
201 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
202 // fog color was already set
208 // FIXME: move this to client?
211 if (gamemode == GAME_NEHAHRA)
213 Cvar_Set("gl_fogenable", "0");
214 Cvar_Set("gl_fogdensity", "0.2");
215 Cvar_Set("gl_fogred", "0.3");
216 Cvar_Set("gl_foggreen", "0.3");
217 Cvar_Set("gl_fogblue", "0.3");
219 fog_density = fog_red = fog_green = fog_blue = 0.0f;
222 // FIXME: move this to client?
223 void FOG_registercvars(void)
228 if (gamemode == GAME_NEHAHRA)
230 Cvar_RegisterVariable (&gl_fogenable);
231 Cvar_RegisterVariable (&gl_fogdensity);
232 Cvar_RegisterVariable (&gl_fogred);
233 Cvar_RegisterVariable (&gl_foggreen);
234 Cvar_RegisterVariable (&gl_fogblue);
235 Cvar_RegisterVariable (&gl_fogstart);
236 Cvar_RegisterVariable (&gl_fogend);
239 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
240 for (x = 0;x < FOGTABLEWIDTH;x++)
242 alpha = exp(r / ((double)x*(double)x));
243 if (x == FOGTABLEWIDTH - 1)
245 fogtable[x] = bound(0, alpha, 1);
249 static void R_BuildBlankTextures(void)
251 unsigned char data[4];
252 data[0] = 128; // normal X
253 data[1] = 128; // normal Y
254 data[2] = 255; // normal Z
255 data[3] = 128; // height
256 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
261 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
266 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
269 static void R_BuildNoTexture(void)
272 unsigned char pix[16][16][4];
273 // this makes a light grey/dark grey checkerboard texture
274 for (y = 0;y < 16;y++)
276 for (x = 0;x < 16;x++)
278 if ((y < 8) ^ (x < 8))
294 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
297 static void R_BuildWhiteCube(void)
299 unsigned char data[6*1*1*4];
300 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
301 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
302 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
303 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
304 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
305 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
306 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
309 static void R_BuildNormalizationCube(void)
313 vec_t s, t, intensity;
315 unsigned char data[6][NORMSIZE][NORMSIZE][4];
316 for (side = 0;side < 6;side++)
318 for (y = 0;y < NORMSIZE;y++)
320 for (x = 0;x < NORMSIZE;x++)
322 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
323 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
358 intensity = 127.0f / sqrt(DotProduct(v, v));
359 data[side][y][x][0] = 128.0f + intensity * v[0];
360 data[side][y][x][1] = 128.0f + intensity * v[1];
361 data[side][y][x][2] = 128.0f + intensity * v[2];
362 data[side][y][x][3] = 255;
366 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
369 static void R_BuildFogTexture(void)
374 unsigned char data1[FOGWIDTH][4];
375 unsigned char data2[FOGWIDTH][4];
376 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
377 for (x = 0;x < FOGWIDTH;x++)
379 alpha = exp(r / ((double)x*(double)x));
380 if (x == FOGWIDTH - 1)
382 b = (int)(256.0 * alpha);
383 b = bound(0, b, 255);
384 data1[x][0] = 255 - b;
385 data1[x][1] = 255 - b;
386 data1[x][2] = 255 - b;
393 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
394 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
397 void gl_main_start(void)
399 r_main_texturepool = R_AllocTexturePool();
400 r_bloom_texture_screen = NULL;
401 r_bloom_texture_bloom = NULL;
402 R_BuildBlankTextures();
404 if (gl_texturecubemap)
407 R_BuildNormalizationCube();
412 void gl_main_shutdown(void)
414 R_FreeTexturePool(&r_main_texturepool);
415 r_bloom_texture_screen = NULL;
416 r_bloom_texture_bloom = NULL;
417 r_texture_blanknormalmap = NULL;
418 r_texture_white = NULL;
419 r_texture_black = NULL;
420 r_texture_whitecube = NULL;
421 r_texture_normalizationcube = NULL;
424 extern void CL_ParseEntityLump(char *entitystring);
425 void gl_main_newmap(void)
427 // FIXME: move this code to client
429 char *entities, entname[MAX_QPATH];
433 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
434 l = (int)strlen(entname) - 4;
435 if (l >= 0 && !strcmp(entname + l, ".bsp"))
437 strcpy(entname + l, ".ent");
438 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
440 CL_ParseEntityLump(entities);
445 if (cl.worldmodel->brush.entities)
446 CL_ParseEntityLump(cl.worldmodel->brush.entities);
450 void GL_Main_Init(void)
452 // FIXME: move this to client?
454 Cvar_RegisterVariable(&r_nearclip);
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;
744 zNear = r_nearclip.value;
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) + r_nearclip.value;
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) + r_nearclip.value;
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)
1171 // don't let sound skip if going slow
1172 if (r_refdef.extraupdate)
1177 R_MeshQueue_BeginScene();
1181 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1182 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1184 if (r_rtworldshadows || r_rtdlightshadows)
1185 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1187 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1189 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1191 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);
1195 R_WorldVisibility();
1196 if (r_timereport_active)
1197 R_TimeReport("worldvis");
1200 if (r_timereport_active)
1201 R_TimeReport("markentity");
1203 R_Shadow_UpdateWorldLightSelection();
1205 for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1211 GL_BlendFunc(GL_ONE, GL_ONE);
1212 GL_DepthTest(!r_showdisabledepthtest.integer);
1213 GL_DepthMask(GL_FALSE);
1214 memset(&m, 0, sizeof(m));
1216 //qglEnable(GL_LINE_SMOOTH);
1217 qglEnable(GL_POLYGON_OFFSET_LINE);
1218 qglPolygonOffset(0, r_showtris_polygonoffset.value);
1222 if (cl.csqc_vidvars.drawworld)
1224 // don't let sound skip if going slow
1225 if (r_refdef.extraupdate)
1229 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1230 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1232 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1233 if (r_timereport_active)
1234 R_TimeReport("worldsky");
1237 if (R_DrawBrushModelsSky() && r_timereport_active)
1238 R_TimeReport("bmodelsky");
1241 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1242 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1244 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1245 if (r_timereport_active)
1246 R_TimeReport("world");
1250 // don't let sound skip if going slow
1251 if (r_refdef.extraupdate)
1255 GL_ShowTrisColor(0, 0.015, 0, 1);
1258 if (r_timereport_active)
1259 R_TimeReport("models");
1261 // don't let sound skip if going slow
1262 if (r_refdef.extraupdate)
1266 GL_ShowTrisColor(0, 0, 0.033, 1);
1267 R_ShadowVolumeLighting(false);
1268 if (r_timereport_active)
1269 R_TimeReport("rtlights");
1271 // don't let sound skip if going slow
1272 if (r_refdef.extraupdate)
1276 GL_ShowTrisColor(0.1, 0, 0, 1);
1278 if (cl.csqc_vidvars.drawworld)
1280 R_DrawLightningBeams();
1281 if (r_timereport_active)
1282 R_TimeReport("lightning");
1285 if (r_timereport_active)
1286 R_TimeReport("particles");
1289 if (r_timereport_active)
1290 R_TimeReport("explosions");
1293 R_MeshQueue_RenderTransparent();
1294 if (r_timereport_active)
1295 R_TimeReport("drawtrans");
1297 if (cl.csqc_vidvars.drawworld)
1300 if (r_timereport_active)
1301 R_TimeReport("coronas");
1303 if(cl.csqc_vidvars.drawcrosshair)
1305 R_DrawWorldCrosshair();
1306 if (r_timereport_active)
1307 R_TimeReport("crosshair");
1310 VM_AddPolygonsToMeshQueue();
1312 R_MeshQueue_Render();
1316 //qglDisable(GL_LINE_SMOOTH);
1317 qglDisable(GL_POLYGON_OFFSET_LINE);
1323 R_MeshQueue_EndScene();
1325 // don't let sound skip if going slow
1326 if (r_refdef.extraupdate)
1331 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1334 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1336 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1337 GL_DepthMask(false);
1339 R_Mesh_Matrix(&identitymatrix);
1341 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1342 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1343 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1344 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1345 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1346 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1347 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1348 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1349 R_FillColors(color, 8, cr, cg, cb, ca);
1352 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1354 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1356 c[0] = c[0] * f1 + fogcolor[0] * f2;
1357 c[1] = c[1] * f1 + fogcolor[1] * f2;
1358 c[2] = c[2] * f1 + fogcolor[2] * f2;
1361 memset(&m, 0, sizeof(m));
1362 m.pointer_vertex = vertex3f;
1363 m.pointer_color = color;
1369 int nomodelelements[24] =
1381 float nomodelvertex3f[6*3] =
1391 float nomodelcolor4f[6*4] =
1393 0.0f, 0.0f, 0.5f, 1.0f,
1394 0.0f, 0.0f, 0.5f, 1.0f,
1395 0.0f, 0.5f, 0.0f, 1.0f,
1396 0.0f, 0.5f, 0.0f, 1.0f,
1397 0.5f, 0.0f, 0.0f, 1.0f,
1398 0.5f, 0.0f, 0.0f, 1.0f
1401 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
1407 R_Mesh_Matrix(&ent->matrix);
1409 memset(&m, 0, sizeof(m));
1410 m.pointer_vertex = nomodelvertex3f;
1412 if (ent->flags & EF_ADDITIVE)
1414 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1415 GL_DepthMask(false);
1417 else if (ent->alpha < 1)
1419 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1420 GL_DepthMask(false);
1424 GL_BlendFunc(GL_ONE, GL_ZERO);
1427 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1430 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1431 m.pointer_color = color4f;
1432 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1434 for (i = 0, c = color4f;i < 6;i++, c += 4)
1436 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1437 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1438 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1442 else if (ent->alpha != 1)
1444 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1445 m.pointer_color = color4f;
1446 for (i = 0, c = color4f;i < 6;i++, c += 4)
1450 m.pointer_color = nomodelcolor4f;
1452 R_Mesh_Draw(0, 6, 8, nomodelelements);
1455 void R_DrawNoModel(entity_render_t *ent)
1457 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1458 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1460 // R_DrawNoModelCallback(ent, 0);
1463 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1465 vec3_t right1, right2, diff, normal;
1467 VectorSubtract (org2, org1, normal);
1469 // calculate 'right' vector for start
1470 VectorSubtract (r_vieworigin, org1, diff);
1471 CrossProduct (normal, diff, right1);
1472 VectorNormalize (right1);
1474 // calculate 'right' vector for end
1475 VectorSubtract (r_vieworigin, org2, diff);
1476 CrossProduct (normal, diff, right2);
1477 VectorNormalize (right2);
1479 vert[ 0] = org1[0] + width * right1[0];
1480 vert[ 1] = org1[1] + width * right1[1];
1481 vert[ 2] = org1[2] + width * right1[2];
1482 vert[ 3] = org1[0] - width * right1[0];
1483 vert[ 4] = org1[1] - width * right1[1];
1484 vert[ 5] = org1[2] - width * right1[2];
1485 vert[ 6] = org2[0] - width * right2[0];
1486 vert[ 7] = org2[1] - width * right2[1];
1487 vert[ 8] = org2[2] - width * right2[2];
1488 vert[ 9] = org2[0] + width * right2[0];
1489 vert[10] = org2[1] + width * right2[1];
1490 vert[11] = org2[2] + width * right2[2];
1493 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1495 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)
1497 float fog = 0.0f, ifog;
1501 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1504 R_Mesh_Matrix(&identitymatrix);
1505 GL_BlendFunc(blendfunc1, blendfunc2);
1506 GL_DepthMask(false);
1507 GL_DepthTest(!depthdisable);
1509 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1510 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1511 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1512 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1513 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1514 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1515 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1516 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1517 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1518 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1519 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1520 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1522 memset(&m, 0, sizeof(m));
1523 m.tex[0] = R_GetTexture(texture);
1524 m.pointer_texcoord[0] = spritetexcoord2f;
1525 m.pointer_vertex = varray_vertex3f;
1527 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
1528 R_Mesh_Draw(0, 4, 2, polygonelements);
1530 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
1532 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
1533 GL_BlendFunc(blendfunc1, GL_ONE);
1534 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
1535 R_Mesh_Draw(0, 4, 2, polygonelements);
1539 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1543 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1544 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1546 if (i == mesh->numvertices)
1548 if (mesh->numvertices < mesh->maxvertices)
1550 VectorCopy(v, vertex3f);
1551 mesh->numvertices++;
1553 return mesh->numvertices;
1559 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1563 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1564 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1565 e = mesh->element3i + mesh->numtriangles * 3;
1566 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1568 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1569 if (mesh->numtriangles < mesh->maxtriangles)
1574 mesh->numtriangles++;
1576 element[1] = element[2];
1580 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1582 int planenum, planenum2;
1585 mplane_t *plane, *plane2;
1586 float temppoints[2][256*3];
1587 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1591 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1592 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1594 if (planenum2 == planenum)
1596 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);
1599 if (tempnumpoints < 3)
1601 // generate elements forming a triangle fan for this polygon
1602 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1606 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
1608 texturelayer_t *layer;
1609 layer = t->currentlayers + t->currentnumlayers++;
1611 layer->depthmask = depthmask;
1612 layer->blendfunc1 = blendfunc1;
1613 layer->blendfunc2 = blendfunc2;
1614 layer->texture = texture;
1615 layer->texmatrix = *matrix;
1616 layer->color[0] = r;
1617 layer->color[1] = g;
1618 layer->color[2] = b;
1619 layer->color[3] = a;
1622 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1624 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1625 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1628 texture_t *texture = t;
1629 model_t *model = ent->model;
1630 int s = ent->skinnum;
1631 if ((unsigned int)s >= (unsigned int)model->numskins)
1633 if (model->skinscenes)
1635 if (model->skinscenes[s].framecount > 1)
1636 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1638 s = model->skinscenes[s].firstframe;
1641 t = t + s * model->num_surfaces;
1643 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];
1644 texture->currentframe = t;
1647 t->currentmaterialflags = t->basematerialflags;
1648 t->currentalpha = ent->alpha;
1649 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1650 t->currentalpha *= r_wateralpha.value;
1651 if (!(ent->flags & RENDER_LIGHT))
1652 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1653 if (ent->effects & EF_ADDITIVE)
1654 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1655 else if (t->currentalpha < 1)
1656 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1657 if (ent->effects & EF_NODEPTHTEST)
1658 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1659 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1660 t->currenttexmatrix = r_waterscrollmatrix;
1662 t->currenttexmatrix = identitymatrix;
1663 t->currentnumlayers = 0;
1664 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1666 if (gl_lightmaps.integer)
1667 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
1668 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1670 // transparent sky would be ridiculous
1671 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1672 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1676 int blendfunc1, blendfunc2, depthmask;
1677 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1679 blendfunc1 = GL_SRC_ALPHA;
1680 blendfunc2 = GL_ONE;
1683 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1685 blendfunc1 = GL_SRC_ALPHA;
1686 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1691 blendfunc1 = GL_ONE;
1692 blendfunc2 = GL_ZERO;
1695 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1697 rtexture_t *currentbasetexture;
1699 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1700 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1701 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
1702 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1704 // fullbright is not affected by r_lightmapintensity
1705 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
1706 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1707 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);
1708 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1709 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);
1715 // q3bsp has no lightmap updates, so the lightstylevalue that
1716 // would normally be baked into the lightmaptexture must be
1717 // applied to the color
1718 if (ent->model->type == mod_brushq3)
1719 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1720 colorscale *= r_lightmapintensity;
1721 if (r_textureunits.integer >= 2 && gl_combine.integer)
1722 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);
1723 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1724 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);
1726 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);
1727 if (r_ambient.value >= (1.0f/64.0f))
1728 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);
1729 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1731 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);
1732 if (r_ambient.value >= (1.0f/64.0f))
1733 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);
1735 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1737 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);
1738 if (r_ambient.value >= (1.0f/64.0f))
1739 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);
1742 if (t->skin.glow != NULL)
1743 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
1744 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1746 // if this is opaque use alpha blend which will darken the earlier
1749 // if this is an alpha blended material, all the earlier passes
1750 // were darkened by fog already, so we only need to add the fog
1751 // color ontop through the fog mask texture
1753 // if this is an additive blended material, all the earlier passes
1754 // were darkened by fog already, and we should not add fog color
1755 // (because the background was not darkened, there is no fog color
1756 // that was lost behind it).
1757 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);
1764 void R_UpdateAllTextureInfo(entity_render_t *ent)
1768 for (i = 0;i < ent->model->num_textures;i++)
1769 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1772 float *rsurface_vertex3f;
1773 float *rsurface_svector3f;
1774 float *rsurface_tvector3f;
1775 float *rsurface_normal3f;
1776 float *rsurface_lightmapcolor4f;
1778 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
1780 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1782 rsurface_vertex3f = varray_vertex3f;
1783 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1784 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
1786 rsurface_svector3f = varray_svector3f;
1787 rsurface_tvector3f = varray_tvector3f;
1788 rsurface_normal3f = varray_normal3f;
1789 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);
1793 rsurface_svector3f = NULL;
1794 rsurface_tvector3f = NULL;
1795 if (generatenormals)
1797 rsurface_normal3f = varray_normal3f;
1798 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);
1801 rsurface_normal3f = NULL;
1806 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1807 rsurface_svector3f = surface->groupmesh->data_svector3f;
1808 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1809 rsurface_normal3f = surface->groupmesh->data_normal3f;
1811 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
1814 float center[3], forward[3], right[3], up[3], v[4][3];
1815 matrix4x4_t matrix1, imatrix1;
1816 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1817 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1818 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1819 // a single autosprite surface can contain multiple sprites...
1820 for (j = 0;j < surface->num_vertices - 3;j += 4)
1822 VectorClear(center);
1823 for (i = 0;i < 4;i++)
1824 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1825 VectorScale(center, 0.25f, center);
1826 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1827 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);
1828 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1829 for (i = 0;i < 4;i++)
1830 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1831 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1833 forward[0] = modelorg[0] - center[0];
1834 forward[1] = modelorg[1] - center[1];
1836 VectorNormalize(forward);
1837 right[0] = forward[1];
1838 right[1] = -forward[0];
1840 VectorSet(up, 0, 0, 1);
1842 for (i = 0;i < 4;i++)
1843 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1845 rsurface_vertex3f = varray_vertex3f;
1846 rsurface_svector3f = varray_svector3f;
1847 rsurface_tvector3f = varray_tvector3f;
1848 rsurface_normal3f = varray_normal3f;
1849 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);
1851 R_Mesh_VertexPointer(rsurface_vertex3f);
1854 static void RSurf_DrawLightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
1859 RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode == 2, false);
1863 vec4_t ambientcolor4f;
1864 vec3_t diffusecolor;
1865 vec3_t diffusenormal;
1866 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1868 rsurface_lightmapcolor4f = varray_color4f;
1869 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);
1878 r = ambientcolor4f[0];
1879 g = ambientcolor4f[1];
1880 b = ambientcolor4f[2];
1881 a = ambientcolor4f[3];
1882 rsurface_lightmapcolor4f = NULL;
1885 else if (lightmode >= 1)
1887 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
1889 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1891 if (surface->lightmapinfo->samples)
1893 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1894 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1895 VectorScale(lm, scale, c);
1896 if (surface->lightmapinfo->styles[1] != 255)
1898 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1900 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1901 VectorMA(c, scale, lm, c);
1902 if (surface->lightmapinfo->styles[2] != 255)
1905 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1906 VectorMA(c, scale, lm, c);
1907 if (surface->lightmapinfo->styles[3] != 255)
1910 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1911 VectorMA(c, scale, lm, c);
1919 rsurface_lightmapcolor4f = varray_color4f;
1922 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1925 rsurface_lightmapcolor4f = NULL;
1928 if (rsurface_lightmapcolor4f)
1930 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)
1932 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1941 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)
1943 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1950 rsurface_lightmapcolor4f = varray_color4f;
1952 if (applycolor && rsurface_lightmapcolor4f)
1954 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)
1961 rsurface_lightmapcolor4f = varray_color4f;
1963 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1964 GL_Color(r, g, b, a);
1965 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1966 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1967 GL_LockArrays(0, 0);
1970 static void RSurf_Draw(const msurface_t *surface)
1972 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1973 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1974 GL_LockArrays(0, 0);
1977 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1979 int texturesurfaceindex;
1981 const msurface_t *surface;
1982 qboolean applycolor;
1985 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1987 renderstats.entities_surfaces += texturenumsurfaces;
1988 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1989 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1990 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1991 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
1992 qglDisable(GL_CULL_FACE);
1993 if (texture->currentnumlayers)
1996 texturelayer_t *layer;
1997 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2000 int layertexrgbscale;
2001 GL_DepthMask(layer->depthmask);
2002 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2003 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2005 layertexrgbscale = 4;
2006 VectorScale(layer->color, 0.25f, layercolor);
2008 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2010 layertexrgbscale = 2;
2011 VectorScale(layer->color, 0.5f, layercolor);
2015 layertexrgbscale = 1;
2016 VectorScale(layer->color, 1.0f, layercolor);
2018 layercolor[3] = layer->color[3];
2019 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2020 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2021 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2022 switch (layer->type)
2024 case TEXTURELAYERTYPE_SKY:
2027 skyrendernow = false;
2028 if (skyrendermasked)
2031 // restore entity matrix and GL_Color
2032 R_Mesh_Matrix(&ent->matrix);
2033 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2036 // LordHavoc: HalfLife maps have freaky skypolys...
2037 //if (!ent->model->brush.ishlbsp)
2039 if (skyrendermasked)
2041 // depth-only (masking)
2042 GL_ColorMask(0,0,0,0);
2043 // just to make sure that braindead drivers don't draw anything
2044 // despite that colormask...
2045 GL_BlendFunc(GL_ZERO, GL_ONE);
2050 GL_BlendFunc(GL_ONE, GL_ZERO);
2052 memset(&m, 0, sizeof(m));
2054 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2056 surface = texturesurfacelist[texturesurfaceindex];
2057 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2058 RSurf_Draw(surface);
2060 if (skyrendermasked)
2061 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2064 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2065 memset(&m, 0, sizeof(m));
2066 m.tex[1] = R_GetTexture(layer->texture);
2067 m.texmatrix[1] = layer->texmatrix;
2068 m.texrgbscale[1] = layertexrgbscale;
2069 m.pointer_color = varray_color4f;
2073 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2075 surface = texturesurfacelist[texturesurfaceindex];
2076 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2077 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2078 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2079 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2084 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2086 surface = texturesurfacelist[texturesurfaceindex];
2087 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2088 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2089 if (surface->lightmaptexture)
2091 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2092 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2096 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2097 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2102 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2103 memset(&m, 0, sizeof(m));
2104 m.tex[0] = R_GetTexture(layer->texture);
2105 m.texmatrix[0] = layer->texmatrix;
2106 m.pointer_color = varray_color4f;
2107 m.texrgbscale[0] = layertexrgbscale;
2111 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2113 surface = texturesurfacelist[texturesurfaceindex];
2114 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2115 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2116 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2121 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2123 surface = texturesurfacelist[texturesurfaceindex];
2124 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2125 if (surface->lightmaptexture)
2127 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2128 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
2132 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2133 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2137 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2138 memset(&m, 0, sizeof(m));
2139 m.tex[0] = R_GetTexture(layer->texture);
2140 m.texmatrix[0] = layer->texmatrix;
2141 m.pointer_color = varray_color4f;
2142 m.texrgbscale[0] = layertexrgbscale;
2144 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2146 surface = texturesurfacelist[texturesurfaceindex];
2147 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2148 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2151 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2152 memset(&m, 0, sizeof(m));
2153 m.tex[0] = R_GetTexture(layer->texture);
2154 m.texmatrix[0] = layer->texmatrix;
2155 m.texrgbscale[0] = layertexrgbscale;
2156 m.pointer_color = varray_color4f;
2160 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2162 surface = texturesurfacelist[texturesurfaceindex];
2163 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2164 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2169 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2171 surface = texturesurfacelist[texturesurfaceindex];
2172 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2173 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2177 case TEXTURELAYERTYPE_TEXTURE:
2178 memset(&m, 0, sizeof(m));
2179 m.tex[0] = R_GetTexture(layer->texture);
2180 m.texmatrix[0] = layer->texmatrix;
2181 m.pointer_color = varray_color4f;
2182 m.texrgbscale[0] = layertexrgbscale;
2184 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2186 surface = texturesurfacelist[texturesurfaceindex];
2187 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2188 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2191 case TEXTURELAYERTYPE_FOG:
2192 memset(&m, 0, sizeof(m));
2195 m.tex[0] = R_GetTexture(layer->texture);
2196 m.texmatrix[0] = layer->texmatrix;
2199 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2203 surface = texturesurfacelist[texturesurfaceindex];
2204 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2206 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2207 R_Mesh_ColorPointer(varray_color4f);
2208 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)
2210 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2211 c[0] = layercolor[0];
2212 c[1] = layercolor[1];
2213 c[2] = layercolor[2];
2214 c[3] = f * layercolor[3];
2216 RSurf_Draw(surface);
2220 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2222 // if trying to do overbright on first pass of an opaque surface
2223 // when combine is not supported, brighten as a post process
2224 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2227 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2228 GL_Color(1, 1, 1, 1);
2229 memset(&m, 0, sizeof(m));
2231 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2233 surface = texturesurfacelist[texturesurfaceindex];
2234 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2235 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2236 RSurf_Draw(surface);
2240 if (r_shownormals.integer && !r_showtrispass)
2244 GL_DepthTest(!r_showdisabledepthtest.integer);
2245 GL_DepthMask(texture->currentlayers->depthmask);
2246 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
2247 memset(&m, 0, sizeof(m));
2249 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2251 surface = texturesurfacelist[texturesurfaceindex];
2252 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2253 GL_Color(1, 0, 0, 1);
2255 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2257 VectorCopy(rsurface_vertex3f + k * 3, v);
2258 qglVertex3f(v[0], v[1], v[2]);
2259 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
2260 qglVertex3f(v[0], v[1], v[2]);
2262 GL_Color(0, 0, 1, 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_tvector3f + k * 3, v);
2268 qglVertex3f(v[0], v[1], v[2]);
2270 GL_Color(0, 1, 0, 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_normal3f + k * 3, v);
2276 qglVertex3f(v[0], v[1], v[2]);
2282 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2283 qglEnable(GL_CULL_FACE);
2286 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2288 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
2292 texture = surface->texture;
2293 if (texture->basematerialflags & MATERIALFLAG_SKY)
2294 return; // transparent sky is too difficult
2295 R_UpdateTextureInfo(ent, texture);
2297 R_Mesh_Matrix(&ent->matrix);
2298 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2299 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2302 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2304 int texturesurfaceindex;
2305 const msurface_t *surface;
2306 vec3_t tempcenter, center;
2307 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2309 // drawing sky transparently would be too difficult
2310 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2312 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2314 surface = texturesurfacelist[texturesurfaceindex];
2315 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2316 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2317 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2318 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2319 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
2324 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2327 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2328 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2330 int i, j, f, flagsmask;
2331 int counttriangles = 0;
2332 msurface_t *surface, **surfacechain;
2333 texture_t *t, *texture;
2334 model_t *model = ent->model;
2336 const int maxsurfacelist = 1024;
2337 int numsurfacelist = 0;
2338 const msurface_t *surfacelist[1024];
2341 R_Mesh_Matrix(&ent->matrix);
2342 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2344 // update light styles
2345 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2347 for (i = 0;i < model->brushq1.light_styles;i++)
2349 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2351 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2352 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2353 for (;(surface = *surfacechain);surfacechain++)
2354 surface->cached_dlight = true;
2359 R_UpdateAllTextureInfo(ent);
2360 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2365 if (ent == r_refdef.worldentity)
2367 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2369 if (!r_worldsurfacevisible[j])
2371 if (t != surface->texture)
2375 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2378 t = surface->texture;
2379 texture = t->currentframe;
2380 f = texture->currentmaterialflags & flagsmask;
2382 if (f && surface->num_triangles)
2384 // if lightmap parameters changed, rebuild lightmap texture
2385 if (surface->cached_dlight)
2386 R_BuildLightMap(ent, surface);
2387 // add face to draw list
2388 surfacelist[numsurfacelist++] = surface;
2389 counttriangles += surface->num_triangles;
2390 if (numsurfacelist >= maxsurfacelist)
2392 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2400 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2402 if (t != surface->texture)
2406 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2409 t = surface->texture;
2410 texture = t->currentframe;
2411 f = texture->currentmaterialflags & flagsmask;
2413 if (f && surface->num_triangles)
2415 // if lightmap parameters changed, rebuild lightmap texture
2416 if (surface->cached_dlight)
2417 R_BuildLightMap(ent, surface);
2418 // add face to draw list
2419 surfacelist[numsurfacelist++] = surface;
2420 counttriangles += surface->num_triangles;
2421 if (numsurfacelist >= maxsurfacelist)
2423 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2430 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2431 if (!r_showtrispass)
2432 renderstats.entities_triangles += counttriangles;