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_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
71 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"};
72 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
73 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"};
74 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"};
75 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
76 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"};
77 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"};
78 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"};
79 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
80 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
81 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
82 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
83 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
84 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
85 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
87 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
88 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
89 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
90 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
91 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
92 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
93 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
95 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)"};
97 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
98 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
99 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
101 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
102 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
103 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
104 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
105 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
107 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"};
109 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"};
111 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
113 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
115 rtexturepool_t *r_main_texturepool;
116 rtexture_t *r_bloom_texture_screen;
117 rtexture_t *r_bloom_texture_bloom;
118 rtexture_t *r_texture_blanknormalmap;
119 rtexture_t *r_texture_white;
120 rtexture_t *r_texture_black;
121 rtexture_t *r_texture_notexture;
122 rtexture_t *r_texture_whitecube;
123 rtexture_t *r_texture_normalizationcube;
124 rtexture_t *r_texture_fogattenuation;
125 rtexture_t *r_texture_fogintensity;
127 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
130 for (i = 0;i < verts;i++)
141 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
144 for (i = 0;i < verts;i++)
159 vec_t fogtabledistmultiplier;
160 float fogtable[FOGTABLEWIDTH];
161 float fog_density, fog_red, fog_green, fog_blue;
163 qboolean oldgl_fogenable;
164 void R_UpdateFog(void)
166 if (gamemode == GAME_NEHAHRA)
168 if (gl_fogenable.integer)
170 oldgl_fogenable = true;
171 fog_density = gl_fogdensity.value;
172 fog_red = gl_fogred.value;
173 fog_green = gl_foggreen.value;
174 fog_blue = gl_fogblue.value;
176 else if (oldgl_fogenable)
178 oldgl_fogenable = false;
187 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
188 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
189 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
194 fogdensity = -4000.0f / (fog_density * fog_density);
195 // this is the point where the fog reaches 0.9986 alpha, which we
196 // consider a good enough cutoff point for the texture
197 // (0.9986 * 256 == 255.6)
198 fogrange = 400 / fog_density;
199 fograngerecip = 1.0f / fogrange;
200 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
201 // fog color was already set
207 // FIXME: move this to client?
210 if (gamemode == GAME_NEHAHRA)
212 Cvar_Set("gl_fogenable", "0");
213 Cvar_Set("gl_fogdensity", "0.2");
214 Cvar_Set("gl_fogred", "0.3");
215 Cvar_Set("gl_foggreen", "0.3");
216 Cvar_Set("gl_fogblue", "0.3");
218 fog_density = fog_red = fog_green = fog_blue = 0.0f;
221 // FIXME: move this to client?
222 void FOG_registercvars(void)
227 if (gamemode == GAME_NEHAHRA)
229 Cvar_RegisterVariable (&gl_fogenable);
230 Cvar_RegisterVariable (&gl_fogdensity);
231 Cvar_RegisterVariable (&gl_fogred);
232 Cvar_RegisterVariable (&gl_foggreen);
233 Cvar_RegisterVariable (&gl_fogblue);
234 Cvar_RegisterVariable (&gl_fogstart);
235 Cvar_RegisterVariable (&gl_fogend);
238 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
239 for (x = 0;x < FOGTABLEWIDTH;x++)
241 alpha = exp(r / ((double)x*(double)x));
242 if (x == FOGTABLEWIDTH - 1)
244 fogtable[x] = bound(0, alpha, 1);
248 static void R_BuildBlankTextures(void)
250 unsigned char data[4];
251 data[0] = 128; // normal X
252 data[1] = 128; // normal Y
253 data[2] = 255; // normal Z
254 data[3] = 128; // height
255 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
260 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
265 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
268 static void R_BuildNoTexture(void)
271 unsigned char pix[16][16][4];
272 // this makes a light grey/dark grey checkerboard texture
273 for (y = 0;y < 16;y++)
275 for (x = 0;x < 16;x++)
277 if ((y < 8) ^ (x < 8))
293 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
296 static void R_BuildWhiteCube(void)
298 unsigned char data[6*1*1*4];
299 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
300 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
301 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
302 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
303 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
304 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
305 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
308 static void R_BuildNormalizationCube(void)
312 vec_t s, t, intensity;
314 unsigned char data[6][NORMSIZE][NORMSIZE][4];
315 for (side = 0;side < 6;side++)
317 for (y = 0;y < NORMSIZE;y++)
319 for (x = 0;x < NORMSIZE;x++)
321 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
322 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
357 intensity = 127.0f / sqrt(DotProduct(v, v));
358 data[side][y][x][0] = 128.0f + intensity * v[0];
359 data[side][y][x][1] = 128.0f + intensity * v[1];
360 data[side][y][x][2] = 128.0f + intensity * v[2];
361 data[side][y][x][3] = 255;
365 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
368 static void R_BuildFogTexture(void)
373 unsigned char data1[FOGWIDTH][4];
374 unsigned char data2[FOGWIDTH][4];
375 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
376 for (x = 0;x < FOGWIDTH;x++)
378 alpha = exp(r / ((double)x*(double)x));
379 if (x == FOGWIDTH - 1)
381 b = (int)(256.0 * alpha);
382 b = bound(0, b, 255);
383 data1[x][0] = 255 - b;
384 data1[x][1] = 255 - b;
385 data1[x][2] = 255 - b;
392 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
393 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
396 void gl_main_start(void)
398 r_main_texturepool = R_AllocTexturePool();
399 r_bloom_texture_screen = NULL;
400 r_bloom_texture_bloom = NULL;
401 R_BuildBlankTextures();
403 if (gl_texturecubemap)
406 R_BuildNormalizationCube();
411 void gl_main_shutdown(void)
413 R_FreeTexturePool(&r_main_texturepool);
414 r_bloom_texture_screen = NULL;
415 r_bloom_texture_bloom = NULL;
416 r_texture_blanknormalmap = NULL;
417 r_texture_white = NULL;
418 r_texture_black = NULL;
419 r_texture_whitecube = NULL;
420 r_texture_normalizationcube = NULL;
423 extern void CL_ParseEntityLump(char *entitystring);
424 void gl_main_newmap(void)
426 // FIXME: move this code to client
428 char *entities, entname[MAX_QPATH];
432 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
433 l = (int)strlen(entname) - 4;
434 if (l >= 0 && !strcmp(entname + l, ".bsp"))
436 strcpy(entname + l, ".ent");
437 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
439 CL_ParseEntityLump(entities);
444 if (cl.worldmodel->brush.entities)
445 CL_ParseEntityLump(cl.worldmodel->brush.entities);
449 void GL_Main_Init(void)
451 // FIXME: move this to client?
453 Cvar_RegisterVariable(&r_showtris);
454 Cvar_RegisterVariable(&r_showtris_polygonoffset);
455 Cvar_RegisterVariable(&r_shownormals);
456 Cvar_RegisterVariable(&r_showlighting);
457 Cvar_RegisterVariable(&r_showshadowvolumes);
458 Cvar_RegisterVariable(&r_showcollisionbrushes);
459 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
460 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
461 Cvar_RegisterVariable(&r_showdisabledepthtest);
462 Cvar_RegisterVariable(&r_drawentities);
463 Cvar_RegisterVariable(&r_drawviewmodel);
464 Cvar_RegisterVariable(&r_speeds);
465 Cvar_RegisterVariable(&r_fullbrights);
466 Cvar_RegisterVariable(&r_wateralpha);
467 Cvar_RegisterVariable(&r_dynamic);
468 Cvar_RegisterVariable(&r_fullbright);
469 Cvar_RegisterVariable(&r_textureunits);
470 Cvar_RegisterVariable(&r_lerpsprites);
471 Cvar_RegisterVariable(&r_lerpmodels);
472 Cvar_RegisterVariable(&r_waterscroll);
473 Cvar_RegisterVariable(&r_bloom);
474 Cvar_RegisterVariable(&r_bloom_intensity);
475 Cvar_RegisterVariable(&r_bloom_blur);
476 Cvar_RegisterVariable(&r_bloom_resolution);
477 Cvar_RegisterVariable(&r_bloom_power);
478 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
479 Cvar_RegisterVariable(&developer_texturelogging);
480 Cvar_RegisterVariable(&gl_lightmaps);
481 Cvar_RegisterVariable(&r_test);
482 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
483 Cvar_SetValue("r_fullbrights", 0);
484 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
487 static vec3_t r_farclip_origin;
488 static vec3_t r_farclip_direction;
489 static vec_t r_farclip_directiondist;
490 static vec_t r_farclip_meshfarclip;
491 static int r_farclip_directionbit0;
492 static int r_farclip_directionbit1;
493 static int r_farclip_directionbit2;
495 // enlarge farclip to accomodate box
496 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
499 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
500 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
501 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
502 if (r_farclip_meshfarclip < d)
503 r_farclip_meshfarclip = d;
506 // return farclip value
507 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
511 VectorCopy(origin, r_farclip_origin);
512 VectorCopy(direction, r_farclip_direction);
513 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
514 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
515 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
516 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
517 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
519 if (r_refdef.worldmodel)
520 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
521 for (i = 0;i < r_refdef.numentities;i++)
522 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
524 return r_farclip_meshfarclip - r_farclip_directiondist;
527 extern void R_Textures_Init(void);
528 extern void GL_Draw_Init(void);
529 extern void GL_Main_Init(void);
530 extern void R_Shadow_Init(void);
531 extern void R_Sky_Init(void);
532 extern void GL_Surf_Init(void);
533 extern void R_Crosshairs_Init(void);
534 extern void R_Light_Init(void);
535 extern void R_Particles_Init(void);
536 extern void R_Explosion_Init(void);
537 extern void gl_backend_init(void);
538 extern void Sbar_Init(void);
539 extern void R_LightningBeams_Init(void);
540 extern void Mod_RenderInit(void);
542 void Render_Init(void)
558 R_LightningBeams_Init();
567 extern char *ENGINE_EXTENSIONS;
570 VID_CheckExtensions();
572 // LordHavoc: report supported extensions
573 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
575 // clear to black (loading plaque will be seen over this)
576 qglClearColor(0,0,0,1);
577 qglClear(GL_COLOR_BUFFER_BIT);
580 int R_CullBox(const vec3_t mins, const vec3_t maxs)
584 for (i = 0;i < 4;i++)
591 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
595 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
599 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
603 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
607 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
611 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
615 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
619 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
627 //==================================================================================
629 static void R_MarkEntities (void)
632 entity_render_t *ent;
634 if (!r_drawentities.integer)
637 r_refdef.worldentity->visframe = r_framecount;
638 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
639 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
641 // worldmodel can check visibility
642 for (i = 0;i < r_refdef.numentities;i++)
644 ent = r_refdef.entities[i];
645 // some of the renderer still relies on origin...
646 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
647 // some of the renderer still relies on scale...
648 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
649 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)))
651 R_UpdateEntLights(ent);
652 ent->visframe = r_framecount;
658 // no worldmodel or it can't check visibility
659 for (i = 0;i < r_refdef.numentities;i++)
661 ent = r_refdef.entities[i];
662 // some of the renderer still relies on origin...
663 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
664 // some of the renderer still relies on scale...
665 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
666 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
668 R_UpdateEntLights(ent);
669 ent->visframe = r_framecount;
675 // only used if skyrendermasked, and normally returns false
676 int R_DrawBrushModelsSky (void)
679 entity_render_t *ent;
681 if (!r_drawentities.integer)
685 for (i = 0;i < r_refdef.numentities;i++)
687 ent = r_refdef.entities[i];
688 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
690 ent->model->DrawSky(ent);
697 void R_DrawNoModel(entity_render_t *ent);
698 void R_DrawModels(void)
701 entity_render_t *ent;
703 if (!r_drawentities.integer)
706 for (i = 0;i < r_refdef.numentities;i++)
708 ent = r_refdef.entities[i];
709 if (ent->visframe == r_framecount)
711 renderstats.entities++;
712 if (ent->model && ent->model->Draw != NULL)
713 ent->model->Draw(ent);
720 static void R_SetFrustum(void)
722 // break apart the view matrix into vectors for various purposes
723 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
724 VectorNegate(r_viewleft, r_viewright);
727 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
728 frustum[0].normal[1] = 0 - 0;
729 frustum[0].normal[2] = -1 - 0;
730 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
731 frustum[1].normal[1] = 0 + 0;
732 frustum[1].normal[2] = -1 + 0;
733 frustum[2].normal[0] = 0 - 0;
734 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
735 frustum[2].normal[2] = -1 - 0;
736 frustum[3].normal[0] = 0 + 0;
737 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
738 frustum[3].normal[2] = -1 + 0;
743 nudge = 1.0 - 1.0 / (1<<23);
744 frustum[4].normal[0] = 0 - 0;
745 frustum[4].normal[1] = 0 - 0;
746 frustum[4].normal[2] = -1 - -nudge;
747 frustum[4].dist = 0 - -2 * zNear * nudge;
748 frustum[5].normal[0] = 0 + 0;
749 frustum[5].normal[1] = 0 + 0;
750 frustum[5].normal[2] = -1 + -nudge;
751 frustum[5].dist = 0 + -2 * zNear * nudge;
757 frustum[0].normal[0] = m[3] - m[0];
758 frustum[0].normal[1] = m[7] - m[4];
759 frustum[0].normal[2] = m[11] - m[8];
760 frustum[0].dist = m[15] - m[12];
762 frustum[1].normal[0] = m[3] + m[0];
763 frustum[1].normal[1] = m[7] + m[4];
764 frustum[1].normal[2] = m[11] + m[8];
765 frustum[1].dist = m[15] + m[12];
767 frustum[2].normal[0] = m[3] - m[1];
768 frustum[2].normal[1] = m[7] - m[5];
769 frustum[2].normal[2] = m[11] - m[9];
770 frustum[2].dist = m[15] - m[13];
772 frustum[3].normal[0] = m[3] + m[1];
773 frustum[3].normal[1] = m[7] + m[5];
774 frustum[3].normal[2] = m[11] + m[9];
775 frustum[3].dist = m[15] + m[13];
777 frustum[4].normal[0] = m[3] - m[2];
778 frustum[4].normal[1] = m[7] - m[6];
779 frustum[4].normal[2] = m[11] - m[10];
780 frustum[4].dist = m[15] - m[14];
782 frustum[5].normal[0] = m[3] + m[2];
783 frustum[5].normal[1] = m[7] + m[6];
784 frustum[5].normal[2] = m[11] + m[10];
785 frustum[5].dist = m[15] + m[14];
790 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
791 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
792 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
793 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
794 VectorCopy(r_viewforward, frustum[4].normal);
795 VectorNormalize(frustum[0].normal);
796 VectorNormalize(frustum[1].normal);
797 VectorNormalize(frustum[2].normal);
798 VectorNormalize(frustum[3].normal);
799 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
800 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
801 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
802 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
803 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
804 PlaneClassify(&frustum[0]);
805 PlaneClassify(&frustum[1]);
806 PlaneClassify(&frustum[2]);
807 PlaneClassify(&frustum[3]);
808 PlaneClassify(&frustum[4]);
810 // LordHavoc: note to all quake engine coders, Quake had a special case
811 // for 90 degrees which assumed a square view (wrong), so I removed it,
812 // Quake2 has it disabled as well.
814 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
815 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
816 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
817 //PlaneClassify(&frustum[0]);
819 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
820 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
821 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
822 //PlaneClassify(&frustum[1]);
824 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
825 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
826 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
827 //PlaneClassify(&frustum[2]);
829 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
830 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
831 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
832 //PlaneClassify(&frustum[3]);
835 //VectorCopy(r_viewforward, frustum[4].normal);
836 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
837 //PlaneClassify(&frustum[4]);
840 static void R_BlendView(void)
842 int screenwidth, screenheight;
847 // set the (poorly named) screenwidth and screenheight variables to
848 // a power of 2 at least as large as the screen, these will define the
849 // size of the texture to allocate
850 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
851 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
853 doblend = r_refdef.viewblend[3] >= 0.01f;
854 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;
856 if (!dobloom && !doblend)
859 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
862 R_Mesh_Matrix(&identitymatrix);
863 // vertex coordinates for a quad that covers the screen exactly
864 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
865 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
866 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
867 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
870 int bloomwidth, bloomheight, x, dobloomblend, range;
871 float xoffset, yoffset, r;
873 // allocate textures as needed
874 if (!r_bloom_texture_screen)
875 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
876 if (!r_bloom_texture_bloom)
877 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
878 // set bloomwidth and bloomheight to the bloom resolution that will be
879 // used (often less than the screen resolution for faster rendering)
880 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
881 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
882 // set up a texcoord array for the full resolution screen image
883 // (we have to keep this around to copy back during final render)
884 varray_texcoord2f[0][0] = 0;
885 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
886 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
887 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
888 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
889 varray_texcoord2f[0][5] = 0;
890 varray_texcoord2f[0][6] = 0;
891 varray_texcoord2f[0][7] = 0;
892 // set up a texcoord array for the reduced resolution bloom image
893 // (which will be additive blended over the screen image)
894 varray_texcoord2f[1][0] = 0;
895 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
896 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
897 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
898 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
899 varray_texcoord2f[1][5] = 0;
900 varray_texcoord2f[1][6] = 0;
901 varray_texcoord2f[1][7] = 0;
902 memset(&m, 0, sizeof(m));
903 m.pointer_vertex = varray_vertex3f;
904 m.pointer_texcoord[0] = varray_texcoord2f[0];
905 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
907 // copy view into the full resolution screen image texture
909 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
910 renderstats.bloom_copypixels += r_view_width * r_view_height;
911 // now scale it down to the bloom size and raise to a power of itself
912 // to darken it (this leaves the really bright stuff bright, and
913 // everything else becomes very dark)
914 // TODO: optimize with multitexture or GLSL
915 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
916 GL_BlendFunc(GL_ONE, GL_ZERO);
917 GL_Color(1, 1, 1, 1);
918 R_Mesh_Draw(0, 4, 2, polygonelements);
919 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
920 // render multiple times with a multiply blendfunc to raise to a power
921 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
922 for (x = 1;x < r_bloom_power.integer;x++)
924 R_Mesh_Draw(0, 4, 2, polygonelements);
925 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
927 // we now have a darkened bloom image in the framebuffer, copy it into
928 // the bloom image texture for more processing
929 memset(&m, 0, sizeof(m));
930 m.pointer_vertex = varray_vertex3f;
931 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
932 m.pointer_texcoord[0] = varray_texcoord2f[2];
935 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
936 renderstats.bloom_copypixels += bloomwidth * bloomheight;
937 // blend on at multiple vertical offsets to achieve a vertical blur
938 // TODO: do offset blends using GLSL
939 range = r_bloom_blur.integer * bloomwidth / 320;
940 GL_BlendFunc(GL_ONE, GL_ZERO);
941 for (x = -range;x <= range;x++)
943 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
944 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
945 // compute a texcoord array with the specified x and y offset
946 varray_texcoord2f[2][0] = xoffset+0;
947 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
948 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
949 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
950 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
951 varray_texcoord2f[2][5] = yoffset+0;
952 varray_texcoord2f[2][6] = xoffset+0;
953 varray_texcoord2f[2][7] = yoffset+0;
954 // this r value looks like a 'dot' particle, fading sharply to
955 // black at the edges
956 // (probably not realistic but looks good enough)
957 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
960 GL_Color(r, r, r, 1);
961 R_Mesh_Draw(0, 4, 2, polygonelements);
962 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
963 GL_BlendFunc(GL_ONE, GL_ONE);
965 // copy the vertically blurred bloom view to a texture
967 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
968 renderstats.bloom_copypixels += bloomwidth * bloomheight;
969 // blend the vertically blurred image at multiple offsets horizontally
970 // to finish the blur effect
971 // TODO: do offset blends using GLSL
972 range = r_bloom_blur.integer * bloomwidth / 320;
973 GL_BlendFunc(GL_ONE, GL_ZERO);
974 for (x = -range;x <= range;x++)
976 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
977 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
978 // compute a texcoord array with the specified x and y offset
979 varray_texcoord2f[2][0] = xoffset+0;
980 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
981 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
982 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
983 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
984 varray_texcoord2f[2][5] = yoffset+0;
985 varray_texcoord2f[2][6] = xoffset+0;
986 varray_texcoord2f[2][7] = yoffset+0;
987 // this r value looks like a 'dot' particle, fading sharply to
988 // black at the edges
989 // (probably not realistic but looks good enough)
990 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
993 GL_Color(r, r, r, 1);
994 R_Mesh_Draw(0, 4, 2, polygonelements);
995 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
996 GL_BlendFunc(GL_ONE, GL_ONE);
998 // copy the blurred bloom view to a texture
1000 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1001 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1002 // go back to full view area
1003 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1004 // put the original screen image back in place and blend the bloom
1006 memset(&m, 0, sizeof(m));
1007 m.pointer_vertex = varray_vertex3f;
1008 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1009 m.pointer_texcoord[0] = varray_texcoord2f[0];
1011 dobloomblend = false;
1013 // do both in one pass if possible
1014 if (r_textureunits.integer >= 2 && gl_combine.integer)
1016 dobloomblend = false;
1017 m.texcombinergb[1] = GL_ADD;
1018 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1019 m.pointer_texcoord[1] = varray_texcoord2f[1];
1022 dobloomblend = true;
1025 GL_BlendFunc(GL_ONE, GL_ZERO);
1027 R_Mesh_Draw(0, 4, 2, polygonelements);
1028 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1029 // now blend on the bloom texture if multipass
1032 memset(&m, 0, sizeof(m));
1033 m.pointer_vertex = varray_vertex3f;
1034 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1035 m.pointer_texcoord[0] = varray_texcoord2f[1];
1037 GL_BlendFunc(GL_ONE, GL_ONE);
1039 R_Mesh_Draw(0, 4, 2, polygonelements);
1040 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1045 // apply a color tint to the whole view
1046 memset(&m, 0, sizeof(m));
1047 m.pointer_vertex = varray_vertex3f;
1049 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1050 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1051 R_Mesh_Draw(0, 4, 2, polygonelements);
1055 void R_RenderScene(void);
1057 matrix4x4_t r_waterscrollmatrix;
1064 void R_RenderView(void)
1066 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1067 return; //Host_Error ("R_RenderView: NULL worldmodel");
1069 r_view_width = bound(0, r_refdef.width, vid.width);
1070 r_view_height = bound(0, r_refdef.height, vid.height);
1072 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1073 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1075 r_view_matrix = r_refdef.viewentitymatrix;
1076 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1077 r_rtworld = r_shadow_realtime_world.integer;
1078 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1079 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1080 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1081 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1083 // GL is weird because it's bottom to top, r_view_y is top to bottom
1084 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1085 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1086 GL_ScissorTest(true);
1091 if (r_timereport_active)
1092 R_TimeReport("setup");
1094 qglDepthFunc(GL_LEQUAL);
1095 qglPolygonOffset(0, 0);
1096 qglEnable(GL_POLYGON_OFFSET_FILL);
1100 qglPolygonOffset(0, 0);
1101 qglDisable(GL_POLYGON_OFFSET_FILL);
1104 if (r_timereport_active)
1105 R_TimeReport("blendview");
1107 GL_Scissor(0, 0, vid.width, vid.height);
1108 GL_ScissorTest(false);
1112 void CSQC_R_ClearScreen (void)
1114 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1115 return; //Host_Error ("R_RenderView: NULL worldmodel");
1117 r_view_width = bound(0, r_refdef.width, vid.width);
1118 r_view_height = bound(0, r_refdef.height, vid.height);
1120 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1121 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1123 r_view_matrix = r_refdef.viewentitymatrix;
1124 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1125 r_rtworld = r_shadow_realtime_world.integer;
1126 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1127 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1128 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1129 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1131 // GL is weird because it's bottom to top, r_view_y is top to bottom
1132 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1133 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1134 GL_ScissorTest(true);
1139 if (r_timereport_active)
1140 R_TimeReport("setup");
1144 void CSQC_R_RenderScene (void)
1146 qglDepthFunc(GL_LEQUAL);
1147 qglPolygonOffset(0, 0);
1148 qglEnable(GL_POLYGON_OFFSET_FILL);
1152 qglPolygonOffset(0, 0);
1153 qglDisable(GL_POLYGON_OFFSET_FILL);
1156 if (r_timereport_active)
1157 R_TimeReport("blendview");
1159 GL_Scissor(0, 0, vid.width, vid.height);
1160 GL_ScissorTest(false);
1163 extern void R_DrawLightningBeams (void);
1164 extern void VM_AddPolygonsToMeshQueue (void);
1165 void R_RenderScene(void)
1167 // don't let sound skip if going slow
1168 if (r_refdef.extraupdate)
1173 R_MeshQueue_BeginScene();
1177 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1178 if (r_rtworldshadows || r_rtdlightshadows)
1179 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f);
1181 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f, r_farclip);
1183 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1185 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);
1189 R_WorldVisibility();
1190 if (r_timereport_active)
1191 R_TimeReport("worldvis");
1194 if (r_timereport_active)
1195 R_TimeReport("markentity");
1197 R_Shadow_UpdateWorldLightSelection();
1199 for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1205 GL_BlendFunc(GL_ONE, GL_ONE);
1206 GL_DepthTest(!r_showdisabledepthtest.integer);
1207 GL_DepthMask(GL_FALSE);
1208 memset(&m, 0, sizeof(m));
1210 //qglEnable(GL_LINE_SMOOTH);
1211 qglEnable(GL_POLYGON_OFFSET_LINE);
1212 qglPolygonOffset(0, r_showtris_polygonoffset.value);
1216 if (cl.csqc_vidvars.drawworld)
1218 // don't let sound skip if going slow
1219 if (r_refdef.extraupdate)
1223 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1224 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1226 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1227 if (r_timereport_active)
1228 R_TimeReport("worldsky");
1231 if (R_DrawBrushModelsSky() && r_timereport_active)
1232 R_TimeReport("bmodelsky");
1235 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1236 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1238 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1239 if (r_timereport_active)
1240 R_TimeReport("world");
1244 // don't let sound skip if going slow
1245 if (r_refdef.extraupdate)
1249 GL_ShowTrisColor(0, 0.015, 0, 1);
1252 if (r_timereport_active)
1253 R_TimeReport("models");
1255 // don't let sound skip if going slow
1256 if (r_refdef.extraupdate)
1260 GL_ShowTrisColor(0, 0, 0.033, 1);
1261 R_ShadowVolumeLighting(false);
1262 if (r_timereport_active)
1263 R_TimeReport("rtlights");
1265 // don't let sound skip if going slow
1266 if (r_refdef.extraupdate)
1270 GL_ShowTrisColor(0.1, 0, 0, 1);
1272 if (cl.csqc_vidvars.drawworld)
1274 R_DrawLightningBeams();
1275 if (r_timereport_active)
1276 R_TimeReport("lightning");
1279 if (r_timereport_active)
1280 R_TimeReport("particles");
1283 if (r_timereport_active)
1284 R_TimeReport("explosions");
1287 R_MeshQueue_RenderTransparent();
1288 if (r_timereport_active)
1289 R_TimeReport("drawtrans");
1291 if (cl.csqc_vidvars.drawworld)
1294 if (r_timereport_active)
1295 R_TimeReport("coronas");
1297 if(cl.csqc_vidvars.drawcrosshair)
1299 R_DrawWorldCrosshair();
1300 if (r_timereport_active)
1301 R_TimeReport("crosshair");
1304 VM_AddPolygonsToMeshQueue();
1306 R_MeshQueue_Render();
1310 //qglDisable(GL_LINE_SMOOTH);
1311 qglDisable(GL_POLYGON_OFFSET_LINE);
1317 R_MeshQueue_EndScene();
1319 // don't let sound skip if going slow
1320 if (r_refdef.extraupdate)
1325 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1328 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1330 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1331 GL_DepthMask(false);
1333 R_Mesh_Matrix(&identitymatrix);
1335 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1336 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1337 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1338 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1339 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1340 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1341 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1342 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1343 R_FillColors(color, 8, cr, cg, cb, ca);
1346 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1348 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1350 c[0] = c[0] * f1 + fogcolor[0] * f2;
1351 c[1] = c[1] * f1 + fogcolor[1] * f2;
1352 c[2] = c[2] * f1 + fogcolor[2] * f2;
1355 memset(&m, 0, sizeof(m));
1356 m.pointer_vertex = vertex3f;
1357 m.pointer_color = color;
1363 int nomodelelements[24] =
1375 float nomodelvertex3f[6*3] =
1385 float nomodelcolor4f[6*4] =
1387 0.0f, 0.0f, 0.5f, 1.0f,
1388 0.0f, 0.0f, 0.5f, 1.0f,
1389 0.0f, 0.5f, 0.0f, 1.0f,
1390 0.0f, 0.5f, 0.0f, 1.0f,
1391 0.5f, 0.0f, 0.0f, 1.0f,
1392 0.5f, 0.0f, 0.0f, 1.0f
1395 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
1401 R_Mesh_Matrix(&ent->matrix);
1403 memset(&m, 0, sizeof(m));
1404 m.pointer_vertex = nomodelvertex3f;
1406 if (ent->flags & EF_ADDITIVE)
1408 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1409 GL_DepthMask(false);
1411 else if (ent->alpha < 1)
1413 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1414 GL_DepthMask(false);
1418 GL_BlendFunc(GL_ONE, GL_ZERO);
1421 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1424 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1425 m.pointer_color = color4f;
1426 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1428 for (i = 0, c = color4f;i < 6;i++, c += 4)
1430 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1431 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1432 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1436 else if (ent->alpha != 1)
1438 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1439 m.pointer_color = color4f;
1440 for (i = 0, c = color4f;i < 6;i++, c += 4)
1444 m.pointer_color = nomodelcolor4f;
1446 R_Mesh_Draw(0, 6, 8, nomodelelements);
1449 void R_DrawNoModel(entity_render_t *ent)
1451 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1452 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1454 // R_DrawNoModelCallback(ent, 0);
1457 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1459 vec3_t right1, right2, diff, normal;
1461 VectorSubtract (org2, org1, normal);
1463 // calculate 'right' vector for start
1464 VectorSubtract (r_vieworigin, org1, diff);
1465 CrossProduct (normal, diff, right1);
1466 VectorNormalize (right1);
1468 // calculate 'right' vector for end
1469 VectorSubtract (r_vieworigin, org2, diff);
1470 CrossProduct (normal, diff, right2);
1471 VectorNormalize (right2);
1473 vert[ 0] = org1[0] + width * right1[0];
1474 vert[ 1] = org1[1] + width * right1[1];
1475 vert[ 2] = org1[2] + width * right1[2];
1476 vert[ 3] = org1[0] - width * right1[0];
1477 vert[ 4] = org1[1] - width * right1[1];
1478 vert[ 5] = org1[2] - width * right1[2];
1479 vert[ 6] = org2[0] - width * right2[0];
1480 vert[ 7] = org2[1] - width * right2[1];
1481 vert[ 8] = org2[2] - width * right2[2];
1482 vert[ 9] = org2[0] + width * right2[0];
1483 vert[10] = org2[1] + width * right2[1];
1484 vert[11] = org2[2] + width * right2[2];
1487 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1489 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)
1491 float fog = 0.0f, ifog;
1495 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1498 R_Mesh_Matrix(&identitymatrix);
1499 GL_BlendFunc(blendfunc1, blendfunc2);
1500 GL_DepthMask(false);
1501 GL_DepthTest(!depthdisable);
1503 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1504 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1505 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1506 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1507 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1508 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1509 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1510 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1511 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1512 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1513 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1514 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1516 memset(&m, 0, sizeof(m));
1517 m.tex[0] = R_GetTexture(texture);
1518 m.pointer_texcoord[0] = spritetexcoord2f;
1519 m.pointer_vertex = varray_vertex3f;
1521 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
1522 R_Mesh_Draw(0, 4, 2, polygonelements);
1524 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
1526 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
1527 GL_BlendFunc(blendfunc1, GL_ONE);
1528 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
1529 R_Mesh_Draw(0, 4, 2, polygonelements);
1533 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1537 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1538 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1540 if (i == mesh->numvertices)
1542 if (mesh->numvertices < mesh->maxvertices)
1544 VectorCopy(v, vertex3f);
1545 mesh->numvertices++;
1547 return mesh->numvertices;
1553 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1557 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1558 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1559 e = mesh->element3i + mesh->numtriangles * 3;
1560 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1562 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1563 if (mesh->numtriangles < mesh->maxtriangles)
1568 mesh->numtriangles++;
1570 element[1] = element[2];
1574 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1576 int planenum, planenum2;
1579 mplane_t *plane, *plane2;
1580 float temppoints[2][256*3];
1581 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1585 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1586 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1588 if (planenum2 == planenum)
1590 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);
1593 if (tempnumpoints < 3)
1595 // generate elements forming a triangle fan for this polygon
1596 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1600 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)
1602 texturelayer_t *layer;
1603 layer = t->currentlayers + t->currentnumlayers++;
1605 layer->depthmask = depthmask;
1606 layer->blendfunc1 = blendfunc1;
1607 layer->blendfunc2 = blendfunc2;
1608 layer->texture = texture;
1609 layer->texmatrix = *matrix;
1610 layer->color[0] = r;
1611 layer->color[1] = g;
1612 layer->color[2] = b;
1613 layer->color[3] = a;
1616 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1618 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1619 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1622 texture_t *texture = t;
1623 model_t *model = ent->model;
1624 int s = ent->skinnum;
1625 if ((unsigned int)s >= (unsigned int)model->numskins)
1627 if (model->skinscenes)
1629 if (model->skinscenes[s].framecount > 1)
1630 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1632 s = model->skinscenes[s].firstframe;
1635 t = t + s * model->num_surfaces;
1637 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];
1638 texture->currentframe = t;
1641 t->currentmaterialflags = t->basematerialflags;
1642 t->currentalpha = ent->alpha;
1643 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1644 t->currentalpha *= r_wateralpha.value;
1645 if (!(ent->flags & RENDER_LIGHT))
1646 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1647 if (ent->effects & EF_ADDITIVE)
1648 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1649 else if (t->currentalpha < 1)
1650 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1651 if (ent->effects & EF_NODEPTHTEST)
1652 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1653 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1654 t->currenttexmatrix = r_waterscrollmatrix;
1656 t->currenttexmatrix = identitymatrix;
1657 t->currentnumlayers = 0;
1658 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1660 if (gl_lightmaps.integer)
1661 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
1662 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1664 // transparent sky would be ridiculous
1665 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1666 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1670 int blendfunc1, blendfunc2, depthmask;
1671 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1673 blendfunc1 = GL_SRC_ALPHA;
1674 blendfunc2 = GL_ONE;
1677 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1679 blendfunc1 = GL_SRC_ALPHA;
1680 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1685 blendfunc1 = GL_ONE;
1686 blendfunc2 = GL_ZERO;
1689 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1691 rtexture_t *currentbasetexture;
1693 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1694 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1695 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
1696 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1698 // fullbright is not affected by r_lightmapintensity
1699 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
1700 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1701 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);
1702 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1703 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);
1709 // q3bsp has no lightmap updates, so the lightstylevalue that
1710 // would normally be baked into the lightmaptexture must be
1711 // applied to the color
1712 if (ent->model->type == mod_brushq3)
1713 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1714 colorscale *= r_lightmapintensity;
1715 if (r_textureunits.integer >= 2 && gl_combine.integer)
1716 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);
1717 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1718 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);
1720 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);
1721 if (r_ambient.value >= (1.0f/64.0f))
1722 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);
1723 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1725 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);
1726 if (r_ambient.value >= (1.0f/64.0f))
1727 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);
1729 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1731 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);
1732 if (r_ambient.value >= (1.0f/64.0f))
1733 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);
1736 if (t->skin.glow != NULL)
1737 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
1738 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1740 // if this is opaque use alpha blend which will darken the earlier
1743 // if this is an alpha blended material, all the earlier passes
1744 // were darkened by fog already, so we only need to add the fog
1745 // color ontop through the fog mask texture
1747 // if this is an additive blended material, all the earlier passes
1748 // were darkened by fog already, and we should not add fog color
1749 // (because the background was not darkened, there is no fog color
1750 // that was lost behind it).
1751 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);
1758 void R_UpdateAllTextureInfo(entity_render_t *ent)
1762 for (i = 0;i < ent->model->num_textures;i++)
1763 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1766 float *rsurface_vertex3f;
1767 float *rsurface_svector3f;
1768 float *rsurface_tvector3f;
1769 float *rsurface_normal3f;
1770 float *rsurface_lightmapcolor4f;
1772 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
1774 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1776 rsurface_vertex3f = varray_vertex3f;
1777 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1778 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
1780 rsurface_svector3f = varray_svector3f;
1781 rsurface_tvector3f = varray_tvector3f;
1782 rsurface_normal3f = varray_normal3f;
1783 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);
1787 rsurface_svector3f = NULL;
1788 rsurface_tvector3f = NULL;
1789 if (generatenormals)
1791 rsurface_normal3f = varray_normal3f;
1792 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);
1795 rsurface_normal3f = NULL;
1800 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1801 rsurface_svector3f = surface->groupmesh->data_svector3f;
1802 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1803 rsurface_normal3f = surface->groupmesh->data_normal3f;
1805 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
1808 float center[3], forward[3], right[3], up[3], v[4][3];
1809 matrix4x4_t matrix1, imatrix1;
1810 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1811 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1812 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1813 // a single autosprite surface can contain multiple sprites...
1814 for (j = 0;j < surface->num_vertices - 3;j += 4)
1816 VectorClear(center);
1817 for (i = 0;i < 4;i++)
1818 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1819 VectorScale(center, 0.25f, center);
1820 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1821 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);
1822 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1823 for (i = 0;i < 4;i++)
1824 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1825 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1827 forward[0] = modelorg[0] - center[0];
1828 forward[1] = modelorg[1] - center[1];
1830 VectorNormalize(forward);
1831 right[0] = forward[1];
1832 right[1] = -forward[0];
1834 VectorSet(up, 0, 0, 1);
1836 for (i = 0;i < 4;i++)
1837 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1839 rsurface_vertex3f = varray_vertex3f;
1840 rsurface_svector3f = varray_svector3f;
1841 rsurface_tvector3f = varray_tvector3f;
1842 rsurface_normal3f = varray_normal3f;
1843 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);
1845 R_Mesh_VertexPointer(rsurface_vertex3f);
1848 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)
1853 RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode == 2, false);
1857 vec4_t ambientcolor4f;
1858 vec3_t diffusecolor;
1859 vec3_t diffusenormal;
1860 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1862 rsurface_lightmapcolor4f = varray_color4f;
1863 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);
1872 r = ambientcolor4f[0];
1873 g = ambientcolor4f[1];
1874 b = ambientcolor4f[2];
1875 a = ambientcolor4f[3];
1876 rsurface_lightmapcolor4f = NULL;
1879 else if (lightmode >= 1)
1881 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
1883 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1885 if (surface->lightmapinfo->samples)
1887 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1888 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1889 VectorScale(lm, scale, c);
1890 if (surface->lightmapinfo->styles[1] != 255)
1892 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1894 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1895 VectorMA(c, scale, lm, c);
1896 if (surface->lightmapinfo->styles[2] != 255)
1899 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1900 VectorMA(c, scale, lm, c);
1901 if (surface->lightmapinfo->styles[3] != 255)
1904 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1905 VectorMA(c, scale, lm, c);
1913 rsurface_lightmapcolor4f = varray_color4f;
1916 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1919 rsurface_lightmapcolor4f = NULL;
1922 if (rsurface_lightmapcolor4f)
1924 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)
1926 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1935 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)
1937 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1944 rsurface_lightmapcolor4f = varray_color4f;
1946 if (applycolor && rsurface_lightmapcolor4f)
1948 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)
1955 rsurface_lightmapcolor4f = varray_color4f;
1957 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1958 GL_Color(r, g, b, a);
1959 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1960 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1961 GL_LockArrays(0, 0);
1964 static void RSurf_Draw(const msurface_t *surface)
1966 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1967 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1968 GL_LockArrays(0, 0);
1971 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1973 int texturesurfaceindex;
1975 const msurface_t *surface;
1976 qboolean applycolor;
1979 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1981 renderstats.entities_surfaces += texturenumsurfaces;
1982 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1983 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1984 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1985 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
1986 qglDisable(GL_CULL_FACE);
1987 if (texture->currentnumlayers)
1990 texturelayer_t *layer;
1991 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1994 int layertexrgbscale;
1995 GL_DepthMask(layer->depthmask);
1996 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1997 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1999 layertexrgbscale = 4;
2000 VectorScale(layer->color, 0.25f, layercolor);
2002 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2004 layertexrgbscale = 2;
2005 VectorScale(layer->color, 0.5f, layercolor);
2009 layertexrgbscale = 1;
2010 VectorScale(layer->color, 1.0f, layercolor);
2012 layercolor[3] = layer->color[3];
2013 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2014 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2015 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2016 switch (layer->type)
2018 case TEXTURELAYERTYPE_SKY:
2021 skyrendernow = false;
2022 if (skyrendermasked)
2025 // restore entity matrix and GL_Color
2026 R_Mesh_Matrix(&ent->matrix);
2027 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2030 // LordHavoc: HalfLife maps have freaky skypolys...
2031 //if (!ent->model->brush.ishlbsp)
2033 if (skyrendermasked)
2035 // depth-only (masking)
2036 GL_ColorMask(0,0,0,0);
2037 // just to make sure that braindead drivers don't draw anything
2038 // despite that colormask...
2039 GL_BlendFunc(GL_ZERO, GL_ONE);
2044 GL_BlendFunc(GL_ONE, GL_ZERO);
2046 memset(&m, 0, sizeof(m));
2048 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2050 surface = texturesurfacelist[texturesurfaceindex];
2051 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2052 RSurf_Draw(surface);
2054 if (skyrendermasked)
2055 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2058 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2059 memset(&m, 0, sizeof(m));
2060 m.tex[1] = R_GetTexture(layer->texture);
2061 m.texmatrix[1] = layer->texmatrix;
2062 m.texrgbscale[1] = layertexrgbscale;
2063 m.pointer_color = varray_color4f;
2067 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2069 surface = texturesurfacelist[texturesurfaceindex];
2070 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2071 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2072 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2073 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2078 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2080 surface = texturesurfacelist[texturesurfaceindex];
2081 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2082 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2083 if (surface->lightmaptexture)
2085 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2086 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2090 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2091 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2096 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2097 memset(&m, 0, sizeof(m));
2098 m.tex[0] = R_GetTexture(layer->texture);
2099 m.texmatrix[0] = layer->texmatrix;
2100 m.pointer_color = varray_color4f;
2101 m.texrgbscale[0] = layertexrgbscale;
2105 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2107 surface = texturesurfacelist[texturesurfaceindex];
2108 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2109 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2110 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2115 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2117 surface = texturesurfacelist[texturesurfaceindex];
2118 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2119 if (surface->lightmaptexture)
2121 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2122 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
2126 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2127 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2131 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2132 memset(&m, 0, sizeof(m));
2133 m.tex[0] = R_GetTexture(layer->texture);
2134 m.texmatrix[0] = layer->texmatrix;
2135 m.pointer_color = varray_color4f;
2136 m.texrgbscale[0] = layertexrgbscale;
2138 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2140 surface = texturesurfacelist[texturesurfaceindex];
2141 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2142 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2145 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2146 memset(&m, 0, sizeof(m));
2147 m.tex[0] = R_GetTexture(layer->texture);
2148 m.texmatrix[0] = layer->texmatrix;
2149 m.texrgbscale[0] = layertexrgbscale;
2150 m.pointer_color = varray_color4f;
2154 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2156 surface = texturesurfacelist[texturesurfaceindex];
2157 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2158 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2163 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2165 surface = texturesurfacelist[texturesurfaceindex];
2166 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2167 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2171 case TEXTURELAYERTYPE_TEXTURE:
2172 memset(&m, 0, sizeof(m));
2173 m.tex[0] = R_GetTexture(layer->texture);
2174 m.texmatrix[0] = layer->texmatrix;
2175 m.pointer_color = varray_color4f;
2176 m.texrgbscale[0] = layertexrgbscale;
2178 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2180 surface = texturesurfacelist[texturesurfaceindex];
2181 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2182 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2185 case TEXTURELAYERTYPE_FOG:
2186 memset(&m, 0, sizeof(m));
2189 m.tex[0] = R_GetTexture(layer->texture);
2190 m.texmatrix[0] = layer->texmatrix;
2193 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2197 surface = texturesurfacelist[texturesurfaceindex];
2198 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2200 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2201 R_Mesh_ColorPointer(varray_color4f);
2202 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)
2204 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2205 c[0] = layercolor[0];
2206 c[1] = layercolor[1];
2207 c[2] = layercolor[2];
2208 c[3] = f * layercolor[3];
2210 RSurf_Draw(surface);
2214 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2216 // if trying to do overbright on first pass of an opaque surface
2217 // when combine is not supported, brighten as a post process
2218 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2221 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2222 GL_Color(1, 1, 1, 1);
2223 memset(&m, 0, sizeof(m));
2225 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2227 surface = texturesurfacelist[texturesurfaceindex];
2228 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2229 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2230 RSurf_Draw(surface);
2234 if (r_shownormals.integer && !r_showtrispass)
2238 GL_DepthTest(!r_showdisabledepthtest.integer);
2239 GL_DepthMask(texture->currentlayers->depthmask);
2240 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
2241 memset(&m, 0, sizeof(m));
2243 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2245 surface = texturesurfacelist[texturesurfaceindex];
2246 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2247 GL_Color(1, 0, 0, 1);
2249 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2251 VectorCopy(rsurface_vertex3f + k * 3, v);
2252 qglVertex3f(v[0], v[1], v[2]);
2253 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
2254 qglVertex3f(v[0], v[1], v[2]);
2256 GL_Color(0, 0, 1, 1);
2257 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2259 VectorCopy(rsurface_vertex3f + k * 3, v);
2260 qglVertex3f(v[0], v[1], v[2]);
2261 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
2262 qglVertex3f(v[0], v[1], v[2]);
2264 GL_Color(0, 1, 0, 1);
2265 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2267 VectorCopy(rsurface_vertex3f + k * 3, v);
2268 qglVertex3f(v[0], v[1], v[2]);
2269 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
2270 qglVertex3f(v[0], v[1], v[2]);
2276 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2277 qglEnable(GL_CULL_FACE);
2280 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2282 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
2286 texture = surface->texture;
2287 if (texture->basematerialflags & MATERIALFLAG_SKY)
2288 return; // transparent sky is too difficult
2289 R_UpdateTextureInfo(ent, texture);
2291 R_Mesh_Matrix(&ent->matrix);
2292 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2293 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2296 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2298 int texturesurfaceindex;
2299 const msurface_t *surface;
2300 vec3_t tempcenter, center;
2301 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2303 // drawing sky transparently would be too difficult
2304 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2306 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2308 surface = texturesurfacelist[texturesurfaceindex];
2309 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2310 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2311 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2312 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2313 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
2318 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2321 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2322 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2324 int i, j, f, flagsmask;
2325 int counttriangles = 0;
2326 msurface_t *surface, **surfacechain;
2327 texture_t *t, *texture;
2328 model_t *model = ent->model;
2330 const int maxsurfacelist = 1024;
2331 int numsurfacelist = 0;
2332 const msurface_t *surfacelist[1024];
2335 R_Mesh_Matrix(&ent->matrix);
2336 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2338 // update light styles
2339 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2341 for (i = 0;i < model->brushq1.light_styles;i++)
2343 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2345 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2346 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2347 for (;(surface = *surfacechain);surfacechain++)
2348 surface->cached_dlight = true;
2353 R_UpdateAllTextureInfo(ent);
2354 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2359 if (ent == r_refdef.worldentity)
2361 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2363 if (!r_worldsurfacevisible[j])
2365 if (t != surface->texture)
2369 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2372 t = surface->texture;
2373 texture = t->currentframe;
2374 f = texture->currentmaterialflags & flagsmask;
2376 if (f && surface->num_triangles)
2378 // if lightmap parameters changed, rebuild lightmap texture
2379 if (surface->cached_dlight)
2380 R_BuildLightMap(ent, surface);
2381 // add face to draw list
2382 surfacelist[numsurfacelist++] = surface;
2383 counttriangles += surface->num_triangles;
2384 if (numsurfacelist >= maxsurfacelist)
2386 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2394 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2396 if (t != surface->texture)
2400 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2403 t = surface->texture;
2404 texture = t->currentframe;
2405 f = texture->currentmaterialflags & flagsmask;
2407 if (f && surface->num_triangles)
2409 // if lightmap parameters changed, rebuild lightmap texture
2410 if (surface->cached_dlight)
2411 R_BuildLightMap(ent, surface);
2412 // add face to draw list
2413 surfacelist[numsurfacelist++] = surface;
2414 counttriangles += surface->num_triangles;
2415 if (numsurfacelist >= maxsurfacelist)
2417 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2424 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2425 if (!r_showtrispass)
2426 renderstats.entities_triangles += counttriangles;