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)
559 R_LightningBeams_Init();
568 extern char *ENGINE_EXTENSIONS;
571 VID_CheckExtensions();
573 // LordHavoc: report supported extensions
574 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
576 // clear to black (loading plaque will be seen over this)
577 qglClearColor(0,0,0,1);
578 qglClear(GL_COLOR_BUFFER_BIT);
581 int R_CullBox(const vec3_t mins, const vec3_t maxs)
585 for (i = 0;i < 4;i++)
592 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
596 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
600 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
604 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
608 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
612 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
616 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
620 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
628 //==================================================================================
630 static void R_MarkEntities (void)
633 entity_render_t *ent;
635 if (!r_drawentities.integer)
638 r_refdef.worldentity->visframe = r_framecount;
639 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
640 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
642 // worldmodel can check visibility
643 for (i = 0;i < r_refdef.numentities;i++)
645 ent = r_refdef.entities[i];
646 // some of the renderer still relies on origin...
647 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
648 // some of the renderer still relies on scale...
649 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
650 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)))
652 R_UpdateEntLights(ent);
653 ent->visframe = r_framecount;
659 // no worldmodel or it can't check visibility
660 for (i = 0;i < r_refdef.numentities;i++)
662 ent = r_refdef.entities[i];
663 // some of the renderer still relies on origin...
664 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
665 // some of the renderer still relies on scale...
666 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
667 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
669 R_UpdateEntLights(ent);
670 ent->visframe = r_framecount;
676 // only used if skyrendermasked, and normally returns false
677 int R_DrawBrushModelsSky (void)
680 entity_render_t *ent;
682 if (!r_drawentities.integer)
686 for (i = 0;i < r_refdef.numentities;i++)
688 ent = r_refdef.entities[i];
689 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
691 ent->model->DrawSky(ent);
698 void R_DrawNoModel(entity_render_t *ent);
699 void R_DrawModels(void)
702 entity_render_t *ent;
704 if (!r_drawentities.integer)
707 for (i = 0;i < r_refdef.numentities;i++)
709 ent = r_refdef.entities[i];
710 if (ent->visframe == r_framecount)
712 renderstats.entities++;
713 if (ent->model && ent->model->Draw != NULL)
714 ent->model->Draw(ent);
721 static void R_SetFrustum(void)
723 // break apart the view matrix into vectors for various purposes
724 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
725 VectorNegate(r_viewleft, r_viewright);
728 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
729 frustum[0].normal[1] = 0 - 0;
730 frustum[0].normal[2] = -1 - 0;
731 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
732 frustum[1].normal[1] = 0 + 0;
733 frustum[1].normal[2] = -1 + 0;
734 frustum[2].normal[0] = 0 - 0;
735 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
736 frustum[2].normal[2] = -1 - 0;
737 frustum[3].normal[0] = 0 + 0;
738 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
739 frustum[3].normal[2] = -1 + 0;
743 zNear = r_nearclip.value;
744 nudge = 1.0 - 1.0 / (1<<23);
745 frustum[4].normal[0] = 0 - 0;
746 frustum[4].normal[1] = 0 - 0;
747 frustum[4].normal[2] = -1 - -nudge;
748 frustum[4].dist = 0 - -2 * zNear * nudge;
749 frustum[5].normal[0] = 0 + 0;
750 frustum[5].normal[1] = 0 + 0;
751 frustum[5].normal[2] = -1 + -nudge;
752 frustum[5].dist = 0 + -2 * zNear * nudge;
758 frustum[0].normal[0] = m[3] - m[0];
759 frustum[0].normal[1] = m[7] - m[4];
760 frustum[0].normal[2] = m[11] - m[8];
761 frustum[0].dist = m[15] - m[12];
763 frustum[1].normal[0] = m[3] + m[0];
764 frustum[1].normal[1] = m[7] + m[4];
765 frustum[1].normal[2] = m[11] + m[8];
766 frustum[1].dist = m[15] + m[12];
768 frustum[2].normal[0] = m[3] - m[1];
769 frustum[2].normal[1] = m[7] - m[5];
770 frustum[2].normal[2] = m[11] - m[9];
771 frustum[2].dist = m[15] - m[13];
773 frustum[3].normal[0] = m[3] + m[1];
774 frustum[3].normal[1] = m[7] + m[5];
775 frustum[3].normal[2] = m[11] + m[9];
776 frustum[3].dist = m[15] + m[13];
778 frustum[4].normal[0] = m[3] - m[2];
779 frustum[4].normal[1] = m[7] - m[6];
780 frustum[4].normal[2] = m[11] - m[10];
781 frustum[4].dist = m[15] - m[14];
783 frustum[5].normal[0] = m[3] + m[2];
784 frustum[5].normal[1] = m[7] + m[6];
785 frustum[5].normal[2] = m[11] + m[10];
786 frustum[5].dist = m[15] + m[14];
791 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
792 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
793 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
794 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
795 VectorCopy(r_viewforward, frustum[4].normal);
796 VectorNormalize(frustum[0].normal);
797 VectorNormalize(frustum[1].normal);
798 VectorNormalize(frustum[2].normal);
799 VectorNormalize(frustum[3].normal);
800 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
801 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
802 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
803 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
804 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
805 PlaneClassify(&frustum[0]);
806 PlaneClassify(&frustum[1]);
807 PlaneClassify(&frustum[2]);
808 PlaneClassify(&frustum[3]);
809 PlaneClassify(&frustum[4]);
811 // LordHavoc: note to all quake engine coders, Quake had a special case
812 // for 90 degrees which assumed a square view (wrong), so I removed it,
813 // Quake2 has it disabled as well.
815 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
816 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
817 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
818 //PlaneClassify(&frustum[0]);
820 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
821 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
822 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
823 //PlaneClassify(&frustum[1]);
825 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
826 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
827 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
828 //PlaneClassify(&frustum[2]);
830 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
831 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
832 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
833 //PlaneClassify(&frustum[3]);
836 //VectorCopy(r_viewforward, frustum[4].normal);
837 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
838 //PlaneClassify(&frustum[4]);
841 static void R_BlendView(void)
843 int screenwidth, screenheight;
848 // set the (poorly named) screenwidth and screenheight variables to
849 // a power of 2 at least as large as the screen, these will define the
850 // size of the texture to allocate
851 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
852 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
854 doblend = r_refdef.viewblend[3] >= 0.01f;
855 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;
857 if (!dobloom && !doblend)
860 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
863 R_Mesh_Matrix(&identitymatrix);
864 // vertex coordinates for a quad that covers the screen exactly
865 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
866 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
867 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
868 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
871 int bloomwidth, bloomheight, x, dobloomblend, range;
872 float xoffset, yoffset, r;
874 // allocate textures as needed
875 if (!r_bloom_texture_screen)
876 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
877 if (!r_bloom_texture_bloom)
878 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
879 // set bloomwidth and bloomheight to the bloom resolution that will be
880 // used (often less than the screen resolution for faster rendering)
881 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
882 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
883 // set up a texcoord array for the full resolution screen image
884 // (we have to keep this around to copy back during final render)
885 varray_texcoord2f[0][0] = 0;
886 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
887 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
888 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
889 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
890 varray_texcoord2f[0][5] = 0;
891 varray_texcoord2f[0][6] = 0;
892 varray_texcoord2f[0][7] = 0;
893 // set up a texcoord array for the reduced resolution bloom image
894 // (which will be additive blended over the screen image)
895 varray_texcoord2f[1][0] = 0;
896 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
897 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
898 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
899 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
900 varray_texcoord2f[1][5] = 0;
901 varray_texcoord2f[1][6] = 0;
902 varray_texcoord2f[1][7] = 0;
903 memset(&m, 0, sizeof(m));
904 m.pointer_vertex = varray_vertex3f;
905 m.pointer_texcoord[0] = varray_texcoord2f[0];
906 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
908 // copy view into the full resolution screen image texture
910 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
911 renderstats.bloom_copypixels += r_view_width * r_view_height;
912 // now scale it down to the bloom size and raise to a power of itself
913 // to darken it (this leaves the really bright stuff bright, and
914 // everything else becomes very dark)
915 // TODO: optimize with multitexture or GLSL
916 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
917 GL_BlendFunc(GL_ONE, GL_ZERO);
918 GL_Color(1, 1, 1, 1);
919 R_Mesh_Draw(0, 4, 2, polygonelements);
920 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
921 // render multiple times with a multiply blendfunc to raise to a power
922 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
923 for (x = 1;x < r_bloom_power.integer;x++)
925 R_Mesh_Draw(0, 4, 2, polygonelements);
926 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
928 // we now have a darkened bloom image in the framebuffer, copy it into
929 // the bloom image texture for more processing
930 memset(&m, 0, sizeof(m));
931 m.pointer_vertex = varray_vertex3f;
932 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
933 m.pointer_texcoord[0] = varray_texcoord2f[2];
936 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
937 renderstats.bloom_copypixels += bloomwidth * bloomheight;
938 // blend on at multiple vertical offsets to achieve a vertical blur
939 // TODO: do offset blends using GLSL
940 range = r_bloom_blur.integer * bloomwidth / 320;
941 GL_BlendFunc(GL_ONE, GL_ZERO);
942 for (x = -range;x <= range;x++)
944 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
945 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
946 // compute a texcoord array with the specified x and y offset
947 varray_texcoord2f[2][0] = xoffset+0;
948 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
949 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
950 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
951 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
952 varray_texcoord2f[2][5] = yoffset+0;
953 varray_texcoord2f[2][6] = xoffset+0;
954 varray_texcoord2f[2][7] = yoffset+0;
955 // this r value looks like a 'dot' particle, fading sharply to
956 // black at the edges
957 // (probably not realistic but looks good enough)
958 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
961 GL_Color(r, r, r, 1);
962 R_Mesh_Draw(0, 4, 2, polygonelements);
963 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
964 GL_BlendFunc(GL_ONE, GL_ONE);
966 // copy the vertically blurred bloom view to a texture
968 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
969 renderstats.bloom_copypixels += bloomwidth * bloomheight;
970 // blend the vertically blurred image at multiple offsets horizontally
971 // to finish the blur effect
972 // TODO: do offset blends using GLSL
973 range = r_bloom_blur.integer * bloomwidth / 320;
974 GL_BlendFunc(GL_ONE, GL_ZERO);
975 for (x = -range;x <= range;x++)
977 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
978 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
979 // compute a texcoord array with the specified x and y offset
980 varray_texcoord2f[2][0] = xoffset+0;
981 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
982 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
983 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
984 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
985 varray_texcoord2f[2][5] = yoffset+0;
986 varray_texcoord2f[2][6] = xoffset+0;
987 varray_texcoord2f[2][7] = yoffset+0;
988 // this r value looks like a 'dot' particle, fading sharply to
989 // black at the edges
990 // (probably not realistic but looks good enough)
991 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
994 GL_Color(r, r, r, 1);
995 R_Mesh_Draw(0, 4, 2, polygonelements);
996 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
997 GL_BlendFunc(GL_ONE, GL_ONE);
999 // copy the blurred bloom view to a texture
1000 GL_ActiveTexture(0);
1001 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1002 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1003 // go back to full view area
1004 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1005 // put the original screen image back in place and blend the bloom
1007 memset(&m, 0, sizeof(m));
1008 m.pointer_vertex = varray_vertex3f;
1009 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1010 m.pointer_texcoord[0] = varray_texcoord2f[0];
1012 dobloomblend = false;
1014 // do both in one pass if possible
1015 if (r_textureunits.integer >= 2 && gl_combine.integer)
1017 dobloomblend = false;
1018 m.texcombinergb[1] = GL_ADD;
1019 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1020 m.pointer_texcoord[1] = varray_texcoord2f[1];
1023 dobloomblend = true;
1026 GL_BlendFunc(GL_ONE, GL_ZERO);
1028 R_Mesh_Draw(0, 4, 2, polygonelements);
1029 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1030 // now blend on the bloom texture if multipass
1033 memset(&m, 0, sizeof(m));
1034 m.pointer_vertex = varray_vertex3f;
1035 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1036 m.pointer_texcoord[0] = varray_texcoord2f[1];
1038 GL_BlendFunc(GL_ONE, GL_ONE);
1040 R_Mesh_Draw(0, 4, 2, polygonelements);
1041 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1046 // apply a color tint to the whole view
1047 memset(&m, 0, sizeof(m));
1048 m.pointer_vertex = varray_vertex3f;
1050 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1051 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1052 R_Mesh_Draw(0, 4, 2, polygonelements);
1056 void R_RenderScene(void);
1058 matrix4x4_t r_waterscrollmatrix;
1065 void R_RenderView(void)
1067 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1068 return; //Host_Error ("R_RenderView: NULL worldmodel");
1070 r_view_width = bound(0, r_refdef.width, vid.width);
1071 r_view_height = bound(0, r_refdef.height, vid.height);
1073 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1074 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1076 r_view_matrix = r_refdef.viewentitymatrix;
1077 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1078 r_rtworld = r_shadow_realtime_world.integer;
1079 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1080 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1081 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1082 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1084 // GL is weird because it's bottom to top, r_view_y is top to bottom
1085 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1086 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1087 GL_ScissorTest(true);
1092 if (r_timereport_active)
1093 R_TimeReport("setup");
1095 qglDepthFunc(GL_LEQUAL);
1096 qglPolygonOffset(0, 0);
1097 qglEnable(GL_POLYGON_OFFSET_FILL);
1101 qglPolygonOffset(0, 0);
1102 qglDisable(GL_POLYGON_OFFSET_FILL);
1105 if (r_timereport_active)
1106 R_TimeReport("blendview");
1108 GL_Scissor(0, 0, vid.width, vid.height);
1109 GL_ScissorTest(false);
1113 void CSQC_R_ClearScreen (void)
1115 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1116 return; //Host_Error ("R_RenderView: NULL worldmodel");
1118 r_view_width = bound(0, r_refdef.width, vid.width);
1119 r_view_height = bound(0, r_refdef.height, vid.height);
1121 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1122 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1124 r_view_matrix = r_refdef.viewentitymatrix;
1125 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1126 r_rtworld = r_shadow_realtime_world.integer;
1127 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1128 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1129 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1130 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1132 // GL is weird because it's bottom to top, r_view_y is top to bottom
1133 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1134 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1135 GL_ScissorTest(true);
1140 if (r_timereport_active)
1141 R_TimeReport("setup");
1145 void CSQC_R_RenderScene (void)
1147 qglDepthFunc(GL_LEQUAL);
1148 qglPolygonOffset(0, 0);
1149 qglEnable(GL_POLYGON_OFFSET_FILL);
1153 qglPolygonOffset(0, 0);
1154 qglDisable(GL_POLYGON_OFFSET_FILL);
1157 if (r_timereport_active)
1158 R_TimeReport("blendview");
1160 GL_Scissor(0, 0, vid.width, vid.height);
1161 GL_ScissorTest(false);
1164 extern void R_DrawLightningBeams (void);
1165 extern void VM_AddPolygonsToMeshQueue (void);
1166 void R_RenderScene(void)
1170 // don't let sound skip if going slow
1171 if (r_refdef.extraupdate)
1176 R_MeshQueue_BeginScene();
1180 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1181 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1183 if (r_rtworldshadows || r_rtdlightshadows)
1184 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1186 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1188 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1190 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);
1194 R_WorldVisibility();
1195 if (r_timereport_active)
1196 R_TimeReport("worldvis");
1199 if (r_timereport_active)
1200 R_TimeReport("markentity");
1202 R_Shadow_UpdateWorldLightSelection();
1204 for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1210 GL_BlendFunc(GL_ONE, GL_ONE);
1211 GL_DepthTest(!r_showdisabledepthtest.integer);
1212 GL_DepthMask(GL_FALSE);
1213 memset(&m, 0, sizeof(m));
1215 //qglEnable(GL_LINE_SMOOTH);
1216 qglEnable(GL_POLYGON_OFFSET_LINE);
1217 qglPolygonOffset(0, r_showtris_polygonoffset.value);
1221 if (cl.csqc_vidvars.drawworld)
1223 // don't let sound skip if going slow
1224 if (r_refdef.extraupdate)
1228 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1229 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1231 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1232 if (r_timereport_active)
1233 R_TimeReport("worldsky");
1236 if (R_DrawBrushModelsSky() && r_timereport_active)
1237 R_TimeReport("bmodelsky");
1240 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1241 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1243 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1244 if (r_timereport_active)
1245 R_TimeReport("world");
1249 // don't let sound skip if going slow
1250 if (r_refdef.extraupdate)
1254 GL_ShowTrisColor(0, 0.015, 0, 1);
1257 if (r_timereport_active)
1258 R_TimeReport("models");
1260 // don't let sound skip if going slow
1261 if (r_refdef.extraupdate)
1265 GL_ShowTrisColor(0, 0, 0.033, 1);
1266 R_ShadowVolumeLighting(false);
1267 if (r_timereport_active)
1268 R_TimeReport("rtlights");
1270 // don't let sound skip if going slow
1271 if (r_refdef.extraupdate)
1275 GL_ShowTrisColor(0.1, 0, 0, 1);
1277 if (cl.csqc_vidvars.drawworld)
1279 R_DrawLightningBeams();
1280 if (r_timereport_active)
1281 R_TimeReport("lightning");
1284 if (r_timereport_active)
1285 R_TimeReport("particles");
1288 if (r_timereport_active)
1289 R_TimeReport("explosions");
1292 R_MeshQueue_RenderTransparent();
1293 if (r_timereport_active)
1294 R_TimeReport("drawtrans");
1296 if (cl.csqc_vidvars.drawworld)
1299 if (r_timereport_active)
1300 R_TimeReport("coronas");
1302 if(cl.csqc_vidvars.drawcrosshair)
1304 R_DrawWorldCrosshair();
1305 if (r_timereport_active)
1306 R_TimeReport("crosshair");
1309 VM_AddPolygonsToMeshQueue();
1311 R_MeshQueue_Render();
1315 //qglDisable(GL_LINE_SMOOTH);
1316 qglDisable(GL_POLYGON_OFFSET_LINE);
1322 R_MeshQueue_EndScene();
1324 // don't let sound skip if going slow
1325 if (r_refdef.extraupdate)
1330 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1333 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1335 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1336 GL_DepthMask(false);
1338 R_Mesh_Matrix(&identitymatrix);
1340 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1341 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1342 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1343 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1344 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1345 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1346 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1347 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1348 R_FillColors(color, 8, cr, cg, cb, ca);
1351 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1353 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1355 c[0] = c[0] * f1 + fogcolor[0] * f2;
1356 c[1] = c[1] * f1 + fogcolor[1] * f2;
1357 c[2] = c[2] * f1 + fogcolor[2] * f2;
1360 memset(&m, 0, sizeof(m));
1361 m.pointer_vertex = vertex3f;
1362 m.pointer_color = color;
1368 int nomodelelements[24] =
1380 float nomodelvertex3f[6*3] =
1390 float nomodelcolor4f[6*4] =
1392 0.0f, 0.0f, 0.5f, 1.0f,
1393 0.0f, 0.0f, 0.5f, 1.0f,
1394 0.0f, 0.5f, 0.0f, 1.0f,
1395 0.0f, 0.5f, 0.0f, 1.0f,
1396 0.5f, 0.0f, 0.0f, 1.0f,
1397 0.5f, 0.0f, 0.0f, 1.0f
1400 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
1406 R_Mesh_Matrix(&ent->matrix);
1408 memset(&m, 0, sizeof(m));
1409 m.pointer_vertex = nomodelvertex3f;
1411 if (ent->flags & EF_ADDITIVE)
1413 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1414 GL_DepthMask(false);
1416 else if (ent->alpha < 1)
1418 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1419 GL_DepthMask(false);
1423 GL_BlendFunc(GL_ONE, GL_ZERO);
1426 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1429 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1430 m.pointer_color = color4f;
1431 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1433 for (i = 0, c = color4f;i < 6;i++, c += 4)
1435 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1436 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1437 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1441 else if (ent->alpha != 1)
1443 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1444 m.pointer_color = color4f;
1445 for (i = 0, c = color4f;i < 6;i++, c += 4)
1449 m.pointer_color = nomodelcolor4f;
1451 R_Mesh_Draw(0, 6, 8, nomodelelements);
1454 void R_DrawNoModel(entity_render_t *ent)
1456 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1457 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1459 // R_DrawNoModelCallback(ent, 0);
1462 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1464 vec3_t right1, right2, diff, normal;
1466 VectorSubtract (org2, org1, normal);
1468 // calculate 'right' vector for start
1469 VectorSubtract (r_vieworigin, org1, diff);
1470 CrossProduct (normal, diff, right1);
1471 VectorNormalize (right1);
1473 // calculate 'right' vector for end
1474 VectorSubtract (r_vieworigin, org2, diff);
1475 CrossProduct (normal, diff, right2);
1476 VectorNormalize (right2);
1478 vert[ 0] = org1[0] + width * right1[0];
1479 vert[ 1] = org1[1] + width * right1[1];
1480 vert[ 2] = org1[2] + width * right1[2];
1481 vert[ 3] = org1[0] - width * right1[0];
1482 vert[ 4] = org1[1] - width * right1[1];
1483 vert[ 5] = org1[2] - width * right1[2];
1484 vert[ 6] = org2[0] - width * right2[0];
1485 vert[ 7] = org2[1] - width * right2[1];
1486 vert[ 8] = org2[2] - width * right2[2];
1487 vert[ 9] = org2[0] + width * right2[0];
1488 vert[10] = org2[1] + width * right2[1];
1489 vert[11] = org2[2] + width * right2[2];
1492 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1494 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)
1496 float fog = 0.0f, ifog;
1500 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1503 R_Mesh_Matrix(&identitymatrix);
1504 GL_BlendFunc(blendfunc1, blendfunc2);
1505 GL_DepthMask(false);
1506 GL_DepthTest(!depthdisable);
1508 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1509 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1510 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1511 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1512 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1513 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1514 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1515 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1516 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1517 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1518 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1519 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1521 memset(&m, 0, sizeof(m));
1522 m.tex[0] = R_GetTexture(texture);
1523 m.pointer_texcoord[0] = spritetexcoord2f;
1524 m.pointer_vertex = varray_vertex3f;
1526 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
1527 R_Mesh_Draw(0, 4, 2, polygonelements);
1529 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
1531 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
1532 GL_BlendFunc(blendfunc1, GL_ONE);
1533 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
1534 R_Mesh_Draw(0, 4, 2, polygonelements);
1538 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1542 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1543 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1545 if (i == mesh->numvertices)
1547 if (mesh->numvertices < mesh->maxvertices)
1549 VectorCopy(v, vertex3f);
1550 mesh->numvertices++;
1552 return mesh->numvertices;
1558 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1562 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1563 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1564 e = mesh->element3i + mesh->numtriangles * 3;
1565 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1567 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1568 if (mesh->numtriangles < mesh->maxtriangles)
1573 mesh->numtriangles++;
1575 element[1] = element[2];
1579 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1581 int planenum, planenum2;
1584 mplane_t *plane, *plane2;
1585 float temppoints[2][256*3];
1586 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1590 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1591 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1593 if (planenum2 == planenum)
1595 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);
1598 if (tempnumpoints < 3)
1600 // generate elements forming a triangle fan for this polygon
1601 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1605 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)
1607 texturelayer_t *layer;
1608 layer = t->currentlayers + t->currentnumlayers++;
1610 layer->depthmask = depthmask;
1611 layer->blendfunc1 = blendfunc1;
1612 layer->blendfunc2 = blendfunc2;
1613 layer->texture = texture;
1614 layer->texmatrix = *matrix;
1615 layer->color[0] = r;
1616 layer->color[1] = g;
1617 layer->color[2] = b;
1618 layer->color[3] = a;
1621 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1623 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1624 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1627 texture_t *texture = t;
1628 model_t *model = ent->model;
1629 int s = ent->skinnum;
1630 if ((unsigned int)s >= (unsigned int)model->numskins)
1632 if (model->skinscenes)
1634 if (model->skinscenes[s].framecount > 1)
1635 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1637 s = model->skinscenes[s].firstframe;
1640 t = t + s * model->num_surfaces;
1642 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];
1643 texture->currentframe = t;
1646 t->currentmaterialflags = t->basematerialflags;
1647 t->currentalpha = ent->alpha;
1648 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1649 t->currentalpha *= r_wateralpha.value;
1650 if (!(ent->flags & RENDER_LIGHT))
1651 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1652 if (ent->effects & EF_ADDITIVE)
1653 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1654 else if (t->currentalpha < 1)
1655 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1656 if (ent->effects & EF_NODEPTHTEST)
1657 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1658 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1659 t->currenttexmatrix = r_waterscrollmatrix;
1661 t->currenttexmatrix = identitymatrix;
1662 t->currentnumlayers = 0;
1663 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1665 if (gl_lightmaps.integer)
1666 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
1667 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1669 // transparent sky would be ridiculous
1670 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1671 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1675 int blendfunc1, blendfunc2, depthmask;
1676 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1678 blendfunc1 = GL_SRC_ALPHA;
1679 blendfunc2 = GL_ONE;
1682 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1684 blendfunc1 = GL_SRC_ALPHA;
1685 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1690 blendfunc1 = GL_ONE;
1691 blendfunc2 = GL_ZERO;
1694 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1696 rtexture_t *currentbasetexture;
1698 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1699 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1700 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
1701 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1703 // fullbright is not affected by r_lightmapintensity
1704 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
1705 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1706 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
1707 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1708 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);
1714 // q3bsp has no lightmap updates, so the lightstylevalue that
1715 // would normally be baked into the lightmaptexture must be
1716 // applied to the color
1717 if (ent->model->type == mod_brushq3)
1718 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1719 colorscale *= r_lightmapintensity;
1720 if (r_textureunits.integer >= 2 && gl_combine.integer)
1721 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);
1722 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1723 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);
1725 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);
1726 if (r_ambient.value >= (1.0f/64.0f))
1727 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);
1728 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1730 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);
1731 if (r_ambient.value >= (1.0f/64.0f))
1732 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);
1734 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1736 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);
1737 if (r_ambient.value >= (1.0f/64.0f))
1738 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);
1741 if (t->skin.glow != NULL)
1742 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
1743 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1745 // if this is opaque use alpha blend which will darken the earlier
1748 // if this is an alpha blended material, all the earlier passes
1749 // were darkened by fog already, so we only need to add the fog
1750 // color ontop through the fog mask texture
1752 // if this is an additive blended material, all the earlier passes
1753 // were darkened by fog already, and we should not add fog color
1754 // (because the background was not darkened, there is no fog color
1755 // that was lost behind it).
1756 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);
1763 void R_UpdateAllTextureInfo(entity_render_t *ent)
1767 for (i = 0;i < ent->model->num_textures;i++)
1768 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1771 float *rsurface_vertex3f;
1772 float *rsurface_svector3f;
1773 float *rsurface_tvector3f;
1774 float *rsurface_normal3f;
1775 float *rsurface_lightmapcolor4f;
1777 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
1779 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1781 rsurface_vertex3f = varray_vertex3f;
1782 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1783 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
1785 rsurface_svector3f = varray_svector3f;
1786 rsurface_tvector3f = varray_tvector3f;
1787 rsurface_normal3f = varray_normal3f;
1788 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);
1792 rsurface_svector3f = NULL;
1793 rsurface_tvector3f = NULL;
1794 if (generatenormals)
1796 rsurface_normal3f = varray_normal3f;
1797 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);
1800 rsurface_normal3f = NULL;
1805 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1806 rsurface_svector3f = surface->groupmesh->data_svector3f;
1807 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1808 rsurface_normal3f = surface->groupmesh->data_normal3f;
1810 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
1813 float center[3], forward[3], right[3], up[3], v[4][3];
1814 matrix4x4_t matrix1, imatrix1;
1815 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1816 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1817 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1818 // a single autosprite surface can contain multiple sprites...
1819 for (j = 0;j < surface->num_vertices - 3;j += 4)
1821 VectorClear(center);
1822 for (i = 0;i < 4;i++)
1823 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1824 VectorScale(center, 0.25f, center);
1825 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1826 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);
1827 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1828 for (i = 0;i < 4;i++)
1829 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1830 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1832 forward[0] = modelorg[0] - center[0];
1833 forward[1] = modelorg[1] - center[1];
1835 VectorNormalize(forward);
1836 right[0] = forward[1];
1837 right[1] = -forward[0];
1839 VectorSet(up, 0, 0, 1);
1841 for (i = 0;i < 4;i++)
1842 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1844 rsurface_vertex3f = varray_vertex3f;
1845 rsurface_svector3f = varray_svector3f;
1846 rsurface_tvector3f = varray_tvector3f;
1847 rsurface_normal3f = varray_normal3f;
1848 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);
1850 R_Mesh_VertexPointer(rsurface_vertex3f);
1853 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)
1858 RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode == 2, false);
1862 vec4_t ambientcolor4f;
1863 vec3_t diffusecolor;
1864 vec3_t diffusenormal;
1865 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1867 rsurface_lightmapcolor4f = varray_color4f;
1868 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);
1877 r = ambientcolor4f[0];
1878 g = ambientcolor4f[1];
1879 b = ambientcolor4f[2];
1880 a = ambientcolor4f[3];
1881 rsurface_lightmapcolor4f = NULL;
1884 else if (lightmode >= 1)
1886 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
1888 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1890 if (surface->lightmapinfo->samples)
1892 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1893 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1894 VectorScale(lm, scale, c);
1895 if (surface->lightmapinfo->styles[1] != 255)
1897 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1899 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1900 VectorMA(c, scale, lm, c);
1901 if (surface->lightmapinfo->styles[2] != 255)
1904 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1905 VectorMA(c, scale, lm, c);
1906 if (surface->lightmapinfo->styles[3] != 255)
1909 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1910 VectorMA(c, scale, lm, c);
1918 rsurface_lightmapcolor4f = varray_color4f;
1921 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1924 rsurface_lightmapcolor4f = NULL;
1927 if (rsurface_lightmapcolor4f)
1929 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)
1931 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1940 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)
1942 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1949 rsurface_lightmapcolor4f = varray_color4f;
1951 if (applycolor && rsurface_lightmapcolor4f)
1953 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)
1960 rsurface_lightmapcolor4f = varray_color4f;
1962 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1963 GL_Color(r, g, b, a);
1964 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1965 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1966 GL_LockArrays(0, 0);
1969 static void RSurf_Draw(const msurface_t *surface)
1971 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1972 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1973 GL_LockArrays(0, 0);
1976 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1978 int texturesurfaceindex;
1980 const msurface_t *surface;
1981 qboolean applycolor;
1984 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1986 renderstats.entities_surfaces += texturenumsurfaces;
1987 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1988 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1989 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1990 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
1991 qglDisable(GL_CULL_FACE);
1992 if (texture->currentnumlayers)
1995 texturelayer_t *layer;
1996 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1999 int layertexrgbscale;
2000 GL_DepthMask(layer->depthmask);
2001 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2002 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2004 layertexrgbscale = 4;
2005 VectorScale(layer->color, 0.25f, layercolor);
2007 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2009 layertexrgbscale = 2;
2010 VectorScale(layer->color, 0.5f, layercolor);
2014 layertexrgbscale = 1;
2015 VectorScale(layer->color, 1.0f, layercolor);
2017 layercolor[3] = layer->color[3];
2018 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2019 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2020 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2021 switch (layer->type)
2023 case TEXTURELAYERTYPE_SKY:
2026 skyrendernow = false;
2027 if (skyrendermasked)
2030 // restore entity matrix and GL_Color
2031 R_Mesh_Matrix(&ent->matrix);
2032 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2035 // LordHavoc: HalfLife maps have freaky skypolys...
2036 //if (!ent->model->brush.ishlbsp)
2038 if (skyrendermasked)
2040 // depth-only (masking)
2041 GL_ColorMask(0,0,0,0);
2042 // just to make sure that braindead drivers don't draw anything
2043 // despite that colormask...
2044 GL_BlendFunc(GL_ZERO, GL_ONE);
2049 GL_BlendFunc(GL_ONE, GL_ZERO);
2051 memset(&m, 0, sizeof(m));
2053 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2055 surface = texturesurfacelist[texturesurfaceindex];
2056 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2057 RSurf_Draw(surface);
2059 if (skyrendermasked)
2060 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2063 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2064 memset(&m, 0, sizeof(m));
2065 m.tex[1] = R_GetTexture(layer->texture);
2066 m.texmatrix[1] = layer->texmatrix;
2067 m.texrgbscale[1] = layertexrgbscale;
2068 m.pointer_color = varray_color4f;
2072 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2074 surface = texturesurfacelist[texturesurfaceindex];
2075 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2076 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2077 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2078 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2083 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2085 surface = texturesurfacelist[texturesurfaceindex];
2086 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2087 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2088 if (surface->lightmaptexture)
2090 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2091 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2095 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2096 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2101 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2102 memset(&m, 0, sizeof(m));
2103 m.tex[0] = R_GetTexture(layer->texture);
2104 m.texmatrix[0] = layer->texmatrix;
2105 m.pointer_color = varray_color4f;
2106 m.texrgbscale[0] = layertexrgbscale;
2110 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2112 surface = texturesurfacelist[texturesurfaceindex];
2113 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2114 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2115 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2120 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2122 surface = texturesurfacelist[texturesurfaceindex];
2123 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2124 if (surface->lightmaptexture)
2126 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2127 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
2131 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2132 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2136 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2137 memset(&m, 0, sizeof(m));
2138 m.tex[0] = R_GetTexture(layer->texture);
2139 m.texmatrix[0] = layer->texmatrix;
2140 m.pointer_color = varray_color4f;
2141 m.texrgbscale[0] = layertexrgbscale;
2143 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2145 surface = texturesurfacelist[texturesurfaceindex];
2146 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2147 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2150 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2151 memset(&m, 0, sizeof(m));
2152 m.tex[0] = R_GetTexture(layer->texture);
2153 m.texmatrix[0] = layer->texmatrix;
2154 m.texrgbscale[0] = layertexrgbscale;
2155 m.pointer_color = varray_color4f;
2159 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2161 surface = texturesurfacelist[texturesurfaceindex];
2162 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2163 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2168 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2170 surface = texturesurfacelist[texturesurfaceindex];
2171 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2172 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2176 case TEXTURELAYERTYPE_TEXTURE:
2177 memset(&m, 0, sizeof(m));
2178 m.tex[0] = R_GetTexture(layer->texture);
2179 m.texmatrix[0] = layer->texmatrix;
2180 m.pointer_color = varray_color4f;
2181 m.texrgbscale[0] = layertexrgbscale;
2183 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2185 surface = texturesurfacelist[texturesurfaceindex];
2186 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2187 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2190 case TEXTURELAYERTYPE_FOG:
2191 memset(&m, 0, sizeof(m));
2194 m.tex[0] = R_GetTexture(layer->texture);
2195 m.texmatrix[0] = layer->texmatrix;
2198 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2202 surface = texturesurfacelist[texturesurfaceindex];
2203 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2205 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2206 R_Mesh_ColorPointer(varray_color4f);
2207 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)
2209 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2210 c[0] = layercolor[0];
2211 c[1] = layercolor[1];
2212 c[2] = layercolor[2];
2213 c[3] = f * layercolor[3];
2215 RSurf_Draw(surface);
2219 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2221 // if trying to do overbright on first pass of an opaque surface
2222 // when combine is not supported, brighten as a post process
2223 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2226 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2227 GL_Color(1, 1, 1, 1);
2228 memset(&m, 0, sizeof(m));
2230 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2232 surface = texturesurfacelist[texturesurfaceindex];
2233 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2234 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2235 RSurf_Draw(surface);
2239 if (r_shownormals.integer && !r_showtrispass)
2243 GL_DepthTest(!r_showdisabledepthtest.integer);
2244 GL_DepthMask(texture->currentlayers->depthmask);
2245 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
2246 memset(&m, 0, sizeof(m));
2248 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2250 surface = texturesurfacelist[texturesurfaceindex];
2251 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2252 GL_Color(1, 0, 0, 1);
2254 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2256 VectorCopy(rsurface_vertex3f + k * 3, v);
2257 qglVertex3f(v[0], v[1], v[2]);
2258 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
2259 qglVertex3f(v[0], v[1], v[2]);
2261 GL_Color(0, 0, 1, 1);
2262 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2264 VectorCopy(rsurface_vertex3f + k * 3, v);
2265 qglVertex3f(v[0], v[1], v[2]);
2266 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
2267 qglVertex3f(v[0], v[1], v[2]);
2269 GL_Color(0, 1, 0, 1);
2270 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2272 VectorCopy(rsurface_vertex3f + k * 3, v);
2273 qglVertex3f(v[0], v[1], v[2]);
2274 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
2275 qglVertex3f(v[0], v[1], v[2]);
2281 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2282 qglEnable(GL_CULL_FACE);
2285 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2287 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
2291 texture = surface->texture;
2292 if (texture->basematerialflags & MATERIALFLAG_SKY)
2293 return; // transparent sky is too difficult
2294 R_UpdateTextureInfo(ent, texture);
2296 R_Mesh_Matrix(&ent->matrix);
2297 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2298 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2301 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2303 int texturesurfaceindex;
2304 const msurface_t *surface;
2305 vec3_t tempcenter, center;
2306 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2308 // drawing sky transparently would be too difficult
2309 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2311 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2313 surface = texturesurfacelist[texturesurfaceindex];
2314 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2315 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2316 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2317 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2318 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
2323 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2326 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2327 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2329 int i, j, f, flagsmask;
2330 int counttriangles = 0;
2331 msurface_t *surface, **surfacechain;
2332 texture_t *t, *texture;
2333 model_t *model = ent->model;
2335 const int maxsurfacelist = 1024;
2336 int numsurfacelist = 0;
2337 const msurface_t *surfacelist[1024];
2340 R_Mesh_Matrix(&ent->matrix);
2341 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2343 // update light styles
2344 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2346 for (i = 0;i < model->brushq1.light_styles;i++)
2348 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2350 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2351 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2352 for (;(surface = *surfacechain);surfacechain++)
2353 surface->cached_dlight = true;
2358 R_UpdateAllTextureInfo(ent);
2359 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2364 if (ent == r_refdef.worldentity)
2366 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2368 if (!r_worldsurfacevisible[j])
2370 if (t != surface->texture)
2374 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2377 t = surface->texture;
2378 texture = t->currentframe;
2379 f = texture->currentmaterialflags & flagsmask;
2381 if (f && surface->num_triangles)
2383 // if lightmap parameters changed, rebuild lightmap texture
2384 if (surface->cached_dlight)
2385 R_BuildLightMap(ent, surface);
2386 // add face to draw list
2387 surfacelist[numsurfacelist++] = surface;
2388 counttriangles += surface->num_triangles;
2389 if (numsurfacelist >= maxsurfacelist)
2391 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2399 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2401 if (t != surface->texture)
2405 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2408 t = surface->texture;
2409 texture = t->currentframe;
2410 f = texture->currentmaterialflags & flagsmask;
2412 if (f && surface->num_triangles)
2414 // if lightmap parameters changed, rebuild lightmap texture
2415 if (surface->cached_dlight)
2416 R_BuildLightMap(ent, surface);
2417 // add face to draw list
2418 surfacelist[numsurfacelist++] = surface;
2419 counttriangles += surface->num_triangles;
2420 if (numsurfacelist >= maxsurfacelist)
2422 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2429 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2430 if (!r_showtrispass)
2431 renderstats.entities_triangles += counttriangles;