2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 // used for dlight push checking and other things
31 matrix4x4_t r_identitymatrix;
33 renderstats_t renderstats;
35 // true during envmap command capture
38 // maximum visible distance (recalculated from world box each frame)
40 // brightness of world lightmaps and related lighting
41 // (often reduced when world rtlights are enabled)
42 float r_lightmapintensity;
43 // whether to draw world lights realtime, dlights realtime, and their shadows
45 qboolean r_rtworldshadows;
47 qboolean r_rtdlightshadows;
50 // forces all rendering to draw triangle outlines
65 matrix4x4_t r_view_matrix;
72 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
73 cvar_t r_showtris_polygonoffset = {0, "r_showtris_polygonoffset", "-10", "nudges triangle outlines in hardware depth units, used to make outlines appear infront of walls"};
74 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
75 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
76 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
77 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
78 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
79 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
80 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing\n"};
81 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
82 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
89 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
90 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
91 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
92 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
93 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
94 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
95 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
97 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
99 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
100 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
101 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
103 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
104 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
105 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
106 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
107 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
109 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
111 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
113 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
115 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
117 rtexturepool_t *r_main_texturepool;
118 rtexture_t *r_bloom_texture_screen;
119 rtexture_t *r_bloom_texture_bloom;
120 rtexture_t *r_texture_blanknormalmap;
121 rtexture_t *r_texture_white;
122 rtexture_t *r_texture_black;
123 rtexture_t *r_texture_notexture;
124 rtexture_t *r_texture_whitecube;
125 rtexture_t *r_texture_normalizationcube;
126 rtexture_t *r_texture_fogattenuation;
127 rtexture_t *r_texture_fogintensity;
129 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
132 for (i = 0;i < verts;i++)
143 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
146 for (i = 0;i < verts;i++)
161 vec_t fogtabledistmultiplier;
162 float fogtable[FOGTABLEWIDTH];
163 float fog_density, fog_red, fog_green, fog_blue;
165 qboolean oldgl_fogenable;
166 void R_UpdateFog(void)
168 if (gamemode == GAME_NEHAHRA)
170 if (gl_fogenable.integer)
172 oldgl_fogenable = true;
173 fog_density = gl_fogdensity.value;
174 fog_red = gl_fogred.value;
175 fog_green = gl_foggreen.value;
176 fog_blue = gl_fogblue.value;
178 else if (oldgl_fogenable)
180 oldgl_fogenable = false;
189 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
190 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
191 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
196 fogdensity = -4000.0f / (fog_density * fog_density);
197 // this is the point where the fog reaches 0.9986 alpha, which we
198 // consider a good enough cutoff point for the texture
199 // (0.9986 * 256 == 255.6)
200 fogrange = 400 / fog_density;
201 fograngerecip = 1.0f / fogrange;
202 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
203 // fog color was already set
209 // FIXME: move this to client?
212 if (gamemode == GAME_NEHAHRA)
214 Cvar_Set("gl_fogenable", "0");
215 Cvar_Set("gl_fogdensity", "0.2");
216 Cvar_Set("gl_fogred", "0.3");
217 Cvar_Set("gl_foggreen", "0.3");
218 Cvar_Set("gl_fogblue", "0.3");
220 fog_density = fog_red = fog_green = fog_blue = 0.0f;
223 // FIXME: move this to client?
224 void FOG_registercvars(void)
229 if (gamemode == GAME_NEHAHRA)
231 Cvar_RegisterVariable (&gl_fogenable);
232 Cvar_RegisterVariable (&gl_fogdensity);
233 Cvar_RegisterVariable (&gl_fogred);
234 Cvar_RegisterVariable (&gl_foggreen);
235 Cvar_RegisterVariable (&gl_fogblue);
236 Cvar_RegisterVariable (&gl_fogstart);
237 Cvar_RegisterVariable (&gl_fogend);
240 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
241 for (x = 0;x < FOGTABLEWIDTH;x++)
243 alpha = exp(r / ((double)x*(double)x));
244 if (x == FOGTABLEWIDTH - 1)
246 fogtable[x] = bound(0, alpha, 1);
250 static void R_BuildBlankTextures(void)
252 unsigned char data[4];
253 data[0] = 128; // normal X
254 data[1] = 128; // normal Y
255 data[2] = 255; // normal Z
256 data[3] = 128; // height
257 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
262 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
267 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
270 static void R_BuildNoTexture(void)
273 unsigned char pix[16][16][4];
274 // this makes a light grey/dark grey checkerboard texture
275 for (y = 0;y < 16;y++)
277 for (x = 0;x < 16;x++)
279 if ((y < 8) ^ (x < 8))
295 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
298 static void R_BuildWhiteCube(void)
300 unsigned char data[6*1*1*4];
301 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
302 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
303 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
304 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
305 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
306 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
307 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
310 static void R_BuildNormalizationCube(void)
314 vec_t s, t, intensity;
316 unsigned char data[6][NORMSIZE][NORMSIZE][4];
317 for (side = 0;side < 6;side++)
319 for (y = 0;y < NORMSIZE;y++)
321 for (x = 0;x < NORMSIZE;x++)
323 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
324 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
359 intensity = 127.0f / sqrt(DotProduct(v, v));
360 data[side][y][x][0] = 128.0f + intensity * v[0];
361 data[side][y][x][1] = 128.0f + intensity * v[1];
362 data[side][y][x][2] = 128.0f + intensity * v[2];
363 data[side][y][x][3] = 255;
367 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
370 static void R_BuildFogTexture(void)
375 unsigned char data1[FOGWIDTH][4];
376 unsigned char data2[FOGWIDTH][4];
377 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
378 for (x = 0;x < FOGWIDTH;x++)
380 alpha = exp(r / ((double)x*(double)x));
381 if (x == FOGWIDTH - 1)
383 b = (int)(256.0 * alpha);
384 b = bound(0, b, 255);
385 data1[x][0] = 255 - b;
386 data1[x][1] = 255 - b;
387 data1[x][2] = 255 - b;
394 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
395 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
398 void gl_main_start(void)
400 r_main_texturepool = R_AllocTexturePool();
401 r_bloom_texture_screen = NULL;
402 r_bloom_texture_bloom = NULL;
403 R_BuildBlankTextures();
405 if (gl_texturecubemap)
408 R_BuildNormalizationCube();
413 void gl_main_shutdown(void)
415 R_FreeTexturePool(&r_main_texturepool);
416 r_bloom_texture_screen = NULL;
417 r_bloom_texture_bloom = NULL;
418 r_texture_blanknormalmap = NULL;
419 r_texture_white = NULL;
420 r_texture_black = NULL;
421 r_texture_whitecube = NULL;
422 r_texture_normalizationcube = NULL;
425 extern void CL_ParseEntityLump(char *entitystring);
426 void gl_main_newmap(void)
428 // FIXME: move this code to client
430 char *entities, entname[MAX_QPATH];
434 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
435 l = (int)strlen(entname) - 4;
436 if (l >= 0 && !strcmp(entname + l, ".bsp"))
438 strcpy(entname + l, ".ent");
439 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
441 CL_ParseEntityLump(entities);
446 if (cl.worldmodel->brush.entities)
447 CL_ParseEntityLump(cl.worldmodel->brush.entities);
451 void GL_Main_Init(void)
453 Matrix4x4_CreateIdentity(&r_identitymatrix);
454 // FIXME: move this to client?
456 Cvar_RegisterVariable(&r_showtris);
457 Cvar_RegisterVariable(&r_showtris_polygonoffset);
458 Cvar_RegisterVariable(&r_shownormals);
459 Cvar_RegisterVariable(&r_showlighting);
460 Cvar_RegisterVariable(&r_showshadowvolumes);
461 Cvar_RegisterVariable(&r_showcollisionbrushes);
462 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
463 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
464 Cvar_RegisterVariable(&r_showdisabledepthtest);
465 Cvar_RegisterVariable(&r_drawentities);
466 Cvar_RegisterVariable(&r_drawviewmodel);
467 Cvar_RegisterVariable(&r_speeds);
468 Cvar_RegisterVariable(&r_fullbrights);
469 Cvar_RegisterVariable(&r_wateralpha);
470 Cvar_RegisterVariable(&r_dynamic);
471 Cvar_RegisterVariable(&r_fullbright);
472 Cvar_RegisterVariable(&r_textureunits);
473 Cvar_RegisterVariable(&r_lerpsprites);
474 Cvar_RegisterVariable(&r_lerpmodels);
475 Cvar_RegisterVariable(&r_waterscroll);
476 Cvar_RegisterVariable(&r_bloom);
477 Cvar_RegisterVariable(&r_bloom_intensity);
478 Cvar_RegisterVariable(&r_bloom_blur);
479 Cvar_RegisterVariable(&r_bloom_resolution);
480 Cvar_RegisterVariable(&r_bloom_power);
481 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
482 Cvar_RegisterVariable(&developer_texturelogging);
483 Cvar_RegisterVariable(&gl_lightmaps);
484 Cvar_RegisterVariable(&r_test);
485 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
486 Cvar_SetValue("r_fullbrights", 0);
487 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
490 static vec3_t r_farclip_origin;
491 static vec3_t r_farclip_direction;
492 static vec_t r_farclip_directiondist;
493 static vec_t r_farclip_meshfarclip;
494 static int r_farclip_directionbit0;
495 static int r_farclip_directionbit1;
496 static int r_farclip_directionbit2;
498 // enlarge farclip to accomodate box
499 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
502 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
503 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
504 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
505 if (r_farclip_meshfarclip < d)
506 r_farclip_meshfarclip = d;
509 // return farclip value
510 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
514 VectorCopy(origin, r_farclip_origin);
515 VectorCopy(direction, r_farclip_direction);
516 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
517 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
518 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
519 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
520 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
522 if (r_refdef.worldmodel)
523 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
524 for (i = 0;i < r_refdef.numentities;i++)
525 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
527 return r_farclip_meshfarclip - r_farclip_directiondist;
530 extern void R_Textures_Init(void);
531 extern void GL_Draw_Init(void);
532 extern void GL_Main_Init(void);
533 extern void R_Shadow_Init(void);
534 extern void R_Sky_Init(void);
535 extern void GL_Surf_Init(void);
536 extern void R_Crosshairs_Init(void);
537 extern void R_Light_Init(void);
538 extern void R_Particles_Init(void);
539 extern void R_Explosion_Init(void);
540 extern void gl_backend_init(void);
541 extern void Sbar_Init(void);
542 extern void R_LightningBeams_Init(void);
543 extern void Mod_RenderInit(void);
545 void Render_Init(void)
561 R_LightningBeams_Init();
570 extern char *ENGINE_EXTENSIONS;
573 VID_CheckExtensions();
575 // LordHavoc: report supported extensions
576 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
578 // clear to black (loading plaque will be seen over this)
579 qglClearColor(0,0,0,1);
580 qglClear(GL_COLOR_BUFFER_BIT);
583 int R_CullBox(const vec3_t mins, const vec3_t maxs)
587 for (i = 0;i < 4;i++)
594 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
598 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
602 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
606 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
610 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
614 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
618 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
622 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
630 //==================================================================================
632 static void R_MarkEntities (void)
635 entity_render_t *ent;
637 if (!r_drawentities.integer)
640 r_refdef.worldentity->visframe = r_framecount;
641 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
642 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
644 // worldmodel can check visibility
645 for (i = 0;i < r_refdef.numentities;i++)
647 ent = r_refdef.entities[i];
648 // some of the renderer still relies on origin...
649 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
650 // some of the renderer still relies on scale...
651 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
652 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_worldleafvisible, ent->mins, ent->maxs)))
654 R_UpdateEntLights(ent);
655 ent->visframe = r_framecount;
661 // no worldmodel or it can't check visibility
662 for (i = 0;i < r_refdef.numentities;i++)
664 ent = r_refdef.entities[i];
665 // some of the renderer still relies on origin...
666 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
667 // some of the renderer still relies on scale...
668 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
669 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
671 R_UpdateEntLights(ent);
672 ent->visframe = r_framecount;
678 // only used if skyrendermasked, and normally returns false
679 int R_DrawBrushModelsSky (void)
682 entity_render_t *ent;
684 if (!r_drawentities.integer)
688 for (i = 0;i < r_refdef.numentities;i++)
690 ent = r_refdef.entities[i];
691 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
693 ent->model->DrawSky(ent);
700 void R_DrawNoModel(entity_render_t *ent);
701 void R_DrawModels(void)
704 entity_render_t *ent;
706 if (!r_drawentities.integer)
709 for (i = 0;i < r_refdef.numentities;i++)
711 ent = r_refdef.entities[i];
712 if (ent->visframe == r_framecount)
714 renderstats.entities++;
715 if (ent->model && ent->model->Draw != NULL)
716 ent->model->Draw(ent);
723 static void R_SetFrustum(void)
725 // break apart the view matrix into vectors for various purposes
726 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
727 VectorNegate(r_viewleft, r_viewright);
730 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
731 frustum[0].normal[1] = 0 - 0;
732 frustum[0].normal[2] = -1 - 0;
733 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
734 frustum[1].normal[1] = 0 + 0;
735 frustum[1].normal[2] = -1 + 0;
736 frustum[2].normal[0] = 0 - 0;
737 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
738 frustum[2].normal[2] = -1 - 0;
739 frustum[3].normal[0] = 0 + 0;
740 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
741 frustum[3].normal[2] = -1 + 0;
746 nudge = 1.0 - 1.0 / (1<<23);
747 frustum[4].normal[0] = 0 - 0;
748 frustum[4].normal[1] = 0 - 0;
749 frustum[4].normal[2] = -1 - -nudge;
750 frustum[4].dist = 0 - -2 * zNear * nudge;
751 frustum[5].normal[0] = 0 + 0;
752 frustum[5].normal[1] = 0 + 0;
753 frustum[5].normal[2] = -1 + -nudge;
754 frustum[5].dist = 0 + -2 * zNear * nudge;
760 frustum[0].normal[0] = m[3] - m[0];
761 frustum[0].normal[1] = m[7] - m[4];
762 frustum[0].normal[2] = m[11] - m[8];
763 frustum[0].dist = m[15] - m[12];
765 frustum[1].normal[0] = m[3] + m[0];
766 frustum[1].normal[1] = m[7] + m[4];
767 frustum[1].normal[2] = m[11] + m[8];
768 frustum[1].dist = m[15] + m[12];
770 frustum[2].normal[0] = m[3] - m[1];
771 frustum[2].normal[1] = m[7] - m[5];
772 frustum[2].normal[2] = m[11] - m[9];
773 frustum[2].dist = m[15] - m[13];
775 frustum[3].normal[0] = m[3] + m[1];
776 frustum[3].normal[1] = m[7] + m[5];
777 frustum[3].normal[2] = m[11] + m[9];
778 frustum[3].dist = m[15] + m[13];
780 frustum[4].normal[0] = m[3] - m[2];
781 frustum[4].normal[1] = m[7] - m[6];
782 frustum[4].normal[2] = m[11] - m[10];
783 frustum[4].dist = m[15] - m[14];
785 frustum[5].normal[0] = m[3] + m[2];
786 frustum[5].normal[1] = m[7] + m[6];
787 frustum[5].normal[2] = m[11] + m[10];
788 frustum[5].dist = m[15] + m[14];
793 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
794 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
795 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
796 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
797 VectorCopy(r_viewforward, frustum[4].normal);
798 VectorNormalize(frustum[0].normal);
799 VectorNormalize(frustum[1].normal);
800 VectorNormalize(frustum[2].normal);
801 VectorNormalize(frustum[3].normal);
802 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
803 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
804 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
805 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
806 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
807 PlaneClassify(&frustum[0]);
808 PlaneClassify(&frustum[1]);
809 PlaneClassify(&frustum[2]);
810 PlaneClassify(&frustum[3]);
811 PlaneClassify(&frustum[4]);
813 // LordHavoc: note to all quake engine coders, Quake had a special case
814 // for 90 degrees which assumed a square view (wrong), so I removed it,
815 // Quake2 has it disabled as well.
817 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
818 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
819 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
820 //PlaneClassify(&frustum[0]);
822 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
823 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
824 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
825 //PlaneClassify(&frustum[1]);
827 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
828 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
829 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
830 //PlaneClassify(&frustum[2]);
832 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
833 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
834 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
835 //PlaneClassify(&frustum[3]);
838 //VectorCopy(r_viewforward, frustum[4].normal);
839 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
840 //PlaneClassify(&frustum[4]);
843 static void R_BlendView(void)
845 int screenwidth, screenheight;
850 // set the (poorly named) screenwidth and screenheight variables to
851 // a power of 2 at least as large as the screen, these will define the
852 // size of the texture to allocate
853 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
854 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
856 doblend = r_refdef.viewblend[3] >= 0.01f;
857 dobloom = r_bloom.integer && screenwidth <= gl_max_texture_size && screenheight <= gl_max_texture_size && r_bloom_resolution.value >= 32 && r_bloom_power.integer >= 1 && r_bloom_power.integer < 100 && r_bloom_blur.value >= 0 && r_bloom_blur.value < 512;
859 if (!dobloom && !doblend)
862 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
865 R_Mesh_Matrix(&r_identitymatrix);
866 // vertex coordinates for a quad that covers the screen exactly
867 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
868 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
869 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
870 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
873 int bloomwidth, bloomheight, x, dobloomblend, range;
874 float xoffset, yoffset, r;
876 // allocate textures as needed
877 if (!r_bloom_texture_screen)
878 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
879 if (!r_bloom_texture_bloom)
880 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
881 // set bloomwidth and bloomheight to the bloom resolution that will be
882 // used (often less than the screen resolution for faster rendering)
883 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
884 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
885 // set up a texcoord array for the full resolution screen image
886 // (we have to keep this around to copy back during final render)
887 varray_texcoord2f[0][0] = 0;
888 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
889 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
890 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
891 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
892 varray_texcoord2f[0][5] = 0;
893 varray_texcoord2f[0][6] = 0;
894 varray_texcoord2f[0][7] = 0;
895 // set up a texcoord array for the reduced resolution bloom image
896 // (which will be additive blended over the screen image)
897 varray_texcoord2f[1][0] = 0;
898 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
899 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
900 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
901 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
902 varray_texcoord2f[1][5] = 0;
903 varray_texcoord2f[1][6] = 0;
904 varray_texcoord2f[1][7] = 0;
905 memset(&m, 0, sizeof(m));
906 m.pointer_vertex = varray_vertex3f;
907 m.pointer_texcoord[0] = varray_texcoord2f[0];
908 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
910 // copy view into the full resolution screen image texture
912 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
913 renderstats.bloom_copypixels += r_view_width * r_view_height;
914 // now scale it down to the bloom size and raise to a power of itself
915 // to darken it (this leaves the really bright stuff bright, and
916 // everything else becomes very dark)
917 // TODO: optimize with multitexture or GLSL
918 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
919 GL_BlendFunc(GL_ONE, GL_ZERO);
920 GL_Color(1, 1, 1, 1);
921 R_Mesh_Draw(0, 4, 2, polygonelements);
922 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
923 // render multiple times with a multiply blendfunc to raise to a power
924 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
925 for (x = 1;x < r_bloom_power.integer;x++)
927 R_Mesh_Draw(0, 4, 2, polygonelements);
928 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
930 // we now have a darkened bloom image in the framebuffer, copy it into
931 // the bloom image texture for more processing
932 memset(&m, 0, sizeof(m));
933 m.pointer_vertex = varray_vertex3f;
934 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
935 m.pointer_texcoord[0] = varray_texcoord2f[2];
938 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
939 renderstats.bloom_copypixels += bloomwidth * bloomheight;
940 // blend on at multiple vertical offsets to achieve a vertical blur
941 // TODO: do offset blends using GLSL
942 range = r_bloom_blur.integer * bloomwidth / 320;
943 GL_BlendFunc(GL_ONE, GL_ZERO);
944 for (x = -range;x <= range;x++)
946 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
947 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
948 // compute a texcoord array with the specified x and y offset
949 varray_texcoord2f[2][0] = xoffset+0;
950 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
951 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
952 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
953 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
954 varray_texcoord2f[2][5] = yoffset+0;
955 varray_texcoord2f[2][6] = xoffset+0;
956 varray_texcoord2f[2][7] = yoffset+0;
957 // this r value looks like a 'dot' particle, fading sharply to
958 // black at the edges
959 // (probably not realistic but looks good enough)
960 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
963 GL_Color(r, r, r, 1);
964 R_Mesh_Draw(0, 4, 2, polygonelements);
965 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
966 GL_BlendFunc(GL_ONE, GL_ONE);
968 // copy the vertically blurred bloom view to a texture
970 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
971 renderstats.bloom_copypixels += bloomwidth * bloomheight;
972 // blend the vertically blurred image at multiple offsets horizontally
973 // to finish the blur effect
974 // TODO: do offset blends using GLSL
975 range = r_bloom_blur.integer * bloomwidth / 320;
976 GL_BlendFunc(GL_ONE, GL_ZERO);
977 for (x = -range;x <= range;x++)
979 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
980 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
981 // compute a texcoord array with the specified x and y offset
982 varray_texcoord2f[2][0] = xoffset+0;
983 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
984 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
985 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
986 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
987 varray_texcoord2f[2][5] = yoffset+0;
988 varray_texcoord2f[2][6] = xoffset+0;
989 varray_texcoord2f[2][7] = yoffset+0;
990 // this r value looks like a 'dot' particle, fading sharply to
991 // black at the edges
992 // (probably not realistic but looks good enough)
993 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
996 GL_Color(r, r, r, 1);
997 R_Mesh_Draw(0, 4, 2, polygonelements);
998 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
999 GL_BlendFunc(GL_ONE, GL_ONE);
1001 // copy the blurred bloom view to a texture
1002 GL_ActiveTexture(0);
1003 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1004 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1005 // go back to full view area
1006 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1007 // put the original screen image back in place and blend the bloom
1009 memset(&m, 0, sizeof(m));
1010 m.pointer_vertex = varray_vertex3f;
1011 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1012 m.pointer_texcoord[0] = varray_texcoord2f[0];
1014 dobloomblend = false;
1016 // do both in one pass if possible
1017 if (r_textureunits.integer >= 2 && gl_combine.integer)
1019 dobloomblend = false;
1020 m.texcombinergb[1] = GL_ADD;
1021 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1022 m.pointer_texcoord[1] = varray_texcoord2f[1];
1025 dobloomblend = true;
1028 GL_BlendFunc(GL_ONE, GL_ZERO);
1030 R_Mesh_Draw(0, 4, 2, polygonelements);
1031 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1032 // now blend on the bloom texture if multipass
1035 memset(&m, 0, sizeof(m));
1036 m.pointer_vertex = varray_vertex3f;
1037 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1038 m.pointer_texcoord[0] = varray_texcoord2f[1];
1040 GL_BlendFunc(GL_ONE, GL_ONE);
1042 R_Mesh_Draw(0, 4, 2, polygonelements);
1043 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1048 // apply a color tint to the whole view
1049 memset(&m, 0, sizeof(m));
1050 m.pointer_vertex = varray_vertex3f;
1052 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1053 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1054 R_Mesh_Draw(0, 4, 2, polygonelements);
1058 void R_RenderScene(void);
1060 matrix4x4_t r_waterscrollmatrix;
1067 void R_RenderView(void)
1069 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1070 return; //Host_Error ("R_RenderView: NULL worldmodel");
1072 r_view_width = bound(0, r_refdef.width, vid.width);
1073 r_view_height = bound(0, r_refdef.height, vid.height);
1075 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1076 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1078 r_view_matrix = r_refdef.viewentitymatrix;
1079 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1080 r_rtworld = r_shadow_realtime_world.integer;
1081 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1082 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1083 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1084 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1086 // GL is weird because it's bottom to top, r_view_y is top to bottom
1087 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1088 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1089 GL_ScissorTest(true);
1094 if (r_timereport_active)
1095 R_TimeReport("setup");
1097 qglDepthFunc(GL_LEQUAL);
1098 qglPolygonOffset(0, 0);
1099 qglEnable(GL_POLYGON_OFFSET_FILL);
1103 qglPolygonOffset(0, 0);
1104 qglDisable(GL_POLYGON_OFFSET_FILL);
1107 if (r_timereport_active)
1108 R_TimeReport("blendview");
1110 GL_Scissor(0, 0, vid.width, vid.height);
1111 GL_ScissorTest(false);
1115 void CSQC_R_ClearScreen (void)
1117 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1118 return; //Host_Error ("R_RenderView: NULL worldmodel");
1120 r_view_width = bound(0, r_refdef.width, vid.width);
1121 r_view_height = bound(0, r_refdef.height, vid.height);
1123 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1124 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1126 r_view_matrix = r_refdef.viewentitymatrix;
1127 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1128 r_rtworld = r_shadow_realtime_world.integer;
1129 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1130 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1131 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1132 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1134 // GL is weird because it's bottom to top, r_view_y is top to bottom
1135 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1136 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1137 GL_ScissorTest(true);
1142 if (r_timereport_active)
1143 R_TimeReport("setup");
1147 void CSQC_R_RenderScene (void)
1149 qglDepthFunc(GL_LEQUAL);
1150 qglPolygonOffset(0, 0);
1151 qglEnable(GL_POLYGON_OFFSET_FILL);
1155 qglPolygonOffset(0, 0);
1156 qglDisable(GL_POLYGON_OFFSET_FILL);
1159 if (r_timereport_active)
1160 R_TimeReport("blendview");
1162 GL_Scissor(0, 0, vid.width, vid.height);
1163 GL_ScissorTest(false);
1166 extern void R_DrawLightningBeams (void);
1167 extern void VM_AddPolygonsToMeshQueue (void);
1168 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 if (r_rtworldshadows || r_rtdlightshadows)
1182 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f);
1184 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f, r_farclip);
1186 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1188 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);
1192 R_WorldVisibility();
1193 if (r_timereport_active)
1194 R_TimeReport("worldvis");
1197 if (r_timereport_active)
1198 R_TimeReport("markentity");
1200 R_Shadow_UpdateWorldLightSelection();
1202 for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1208 GL_BlendFunc(GL_ONE, GL_ONE);
1209 GL_DepthTest(!r_showdisabledepthtest.integer);
1210 GL_DepthMask(GL_FALSE);
1211 memset(&m, 0, sizeof(m));
1213 //qglEnable(GL_LINE_SMOOTH);
1214 qglEnable(GL_POLYGON_OFFSET_LINE);
1215 qglPolygonOffset(0, r_showtris_polygonoffset.value);
1219 if (cl.csqc_vidvars.drawworld)
1221 // don't let sound skip if going slow
1222 if (r_refdef.extraupdate)
1226 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1227 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1229 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1230 if (r_timereport_active)
1231 R_TimeReport("worldsky");
1234 if (R_DrawBrushModelsSky() && r_timereport_active)
1235 R_TimeReport("bmodelsky");
1238 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1239 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1241 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1242 if (r_timereport_active)
1243 R_TimeReport("world");
1247 // don't let sound skip if going slow
1248 if (r_refdef.extraupdate)
1252 GL_ShowTrisColor(0, 0.015, 0, 1);
1255 if (r_timereport_active)
1256 R_TimeReport("models");
1258 // don't let sound skip if going slow
1259 if (r_refdef.extraupdate)
1263 GL_ShowTrisColor(0, 0, 0.033, 1);
1264 R_ShadowVolumeLighting(false);
1265 if (r_timereport_active)
1266 R_TimeReport("rtlights");
1268 // don't let sound skip if going slow
1269 if (r_refdef.extraupdate)
1273 GL_ShowTrisColor(0.1, 0, 0, 1);
1275 if (cl.csqc_vidvars.drawworld)
1277 R_DrawLightningBeams();
1278 if (r_timereport_active)
1279 R_TimeReport("lightning");
1282 if (r_timereport_active)
1283 R_TimeReport("particles");
1286 if (r_timereport_active)
1287 R_TimeReport("explosions");
1290 R_MeshQueue_RenderTransparent();
1291 if (r_timereport_active)
1292 R_TimeReport("drawtrans");
1294 if (cl.csqc_vidvars.drawworld)
1297 if (r_timereport_active)
1298 R_TimeReport("coronas");
1300 if(cl.csqc_vidvars.drawcrosshair)
1302 R_DrawWorldCrosshair();
1303 if (r_timereport_active)
1304 R_TimeReport("crosshair");
1307 VM_AddPolygonsToMeshQueue();
1309 R_MeshQueue_Render();
1313 //qglDisable(GL_LINE_SMOOTH);
1314 qglDisable(GL_POLYGON_OFFSET_LINE);
1320 R_MeshQueue_EndScene();
1322 // don't let sound skip if going slow
1323 if (r_refdef.extraupdate)
1328 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1331 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1333 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1334 GL_DepthMask(false);
1336 R_Mesh_Matrix(&r_identitymatrix);
1338 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1339 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1340 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1341 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1342 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1343 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1344 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1345 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1346 R_FillColors(color, 8, cr, cg, cb, ca);
1349 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1351 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1353 c[0] = c[0] * f1 + fogcolor[0] * f2;
1354 c[1] = c[1] * f1 + fogcolor[1] * f2;
1355 c[2] = c[2] * f1 + fogcolor[2] * f2;
1358 memset(&m, 0, sizeof(m));
1359 m.pointer_vertex = vertex3f;
1360 m.pointer_color = color;
1366 int nomodelelements[24] =
1378 float nomodelvertex3f[6*3] =
1388 float nomodelcolor4f[6*4] =
1390 0.0f, 0.0f, 0.5f, 1.0f,
1391 0.0f, 0.0f, 0.5f, 1.0f,
1392 0.0f, 0.5f, 0.0f, 1.0f,
1393 0.0f, 0.5f, 0.0f, 1.0f,
1394 0.5f, 0.0f, 0.0f, 1.0f,
1395 0.5f, 0.0f, 0.0f, 1.0f
1398 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
1404 R_Mesh_Matrix(&ent->matrix);
1406 memset(&m, 0, sizeof(m));
1407 m.pointer_vertex = nomodelvertex3f;
1409 if (ent->flags & EF_ADDITIVE)
1411 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1412 GL_DepthMask(false);
1414 else if (ent->alpha < 1)
1416 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1417 GL_DepthMask(false);
1421 GL_BlendFunc(GL_ONE, GL_ZERO);
1424 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1427 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1428 m.pointer_color = color4f;
1429 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1431 for (i = 0, c = color4f;i < 6;i++, c += 4)
1433 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1434 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1435 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1439 else if (ent->alpha != 1)
1441 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1442 m.pointer_color = color4f;
1443 for (i = 0, c = color4f;i < 6;i++, c += 4)
1447 m.pointer_color = nomodelcolor4f;
1449 R_Mesh_Draw(0, 6, 8, nomodelelements);
1452 void R_DrawNoModel(entity_render_t *ent)
1454 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1455 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1457 // R_DrawNoModelCallback(ent, 0);
1460 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1462 vec3_t right1, right2, diff, normal;
1464 VectorSubtract (org2, org1, normal);
1466 // calculate 'right' vector for start
1467 VectorSubtract (r_vieworigin, org1, diff);
1468 CrossProduct (normal, diff, right1);
1469 VectorNormalize (right1);
1471 // calculate 'right' vector for end
1472 VectorSubtract (r_vieworigin, org2, diff);
1473 CrossProduct (normal, diff, right2);
1474 VectorNormalize (right2);
1476 vert[ 0] = org1[0] + width * right1[0];
1477 vert[ 1] = org1[1] + width * right1[1];
1478 vert[ 2] = org1[2] + width * right1[2];
1479 vert[ 3] = org1[0] - width * right1[0];
1480 vert[ 4] = org1[1] - width * right1[1];
1481 vert[ 5] = org1[2] - width * right1[2];
1482 vert[ 6] = org2[0] - width * right2[0];
1483 vert[ 7] = org2[1] - width * right2[1];
1484 vert[ 8] = org2[2] - width * right2[2];
1485 vert[ 9] = org2[0] + width * right2[0];
1486 vert[10] = org2[1] + width * right2[1];
1487 vert[11] = org2[2] + width * right2[2];
1490 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1492 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)
1494 float fog = 0.0f, ifog;
1498 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1501 R_Mesh_Matrix(&r_identitymatrix);
1502 GL_BlendFunc(blendfunc1, blendfunc2);
1503 GL_DepthMask(false);
1504 GL_DepthTest(!depthdisable);
1506 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1507 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1508 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1509 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1510 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1511 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1512 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1513 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1514 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1515 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1516 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1517 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1519 memset(&m, 0, sizeof(m));
1520 m.tex[0] = R_GetTexture(texture);
1521 m.pointer_texcoord[0] = spritetexcoord2f;
1522 m.pointer_vertex = varray_vertex3f;
1524 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
1525 R_Mesh_Draw(0, 4, 2, polygonelements);
1527 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
1529 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
1530 GL_BlendFunc(blendfunc1, GL_ONE);
1531 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
1532 R_Mesh_Draw(0, 4, 2, polygonelements);
1536 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1540 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1541 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1543 if (i == mesh->numvertices)
1545 if (mesh->numvertices < mesh->maxvertices)
1547 VectorCopy(v, vertex3f);
1548 mesh->numvertices++;
1550 return mesh->numvertices;
1556 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1560 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1561 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1562 e = mesh->element3i + mesh->numtriangles * 3;
1563 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1565 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1566 if (mesh->numtriangles < mesh->maxtriangles)
1571 mesh->numtriangles++;
1573 element[1] = element[2];
1577 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1579 int planenum, planenum2;
1582 mplane_t *plane, *plane2;
1583 float temppoints[2][256*3];
1584 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1588 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1589 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1591 if (planenum2 == planenum)
1593 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);
1596 if (tempnumpoints < 3)
1598 // generate elements forming a triangle fan for this polygon
1599 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1603 void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, matrix4x4_t *matrix, float r, float g, float b, float a)
1605 texturelayer_t *layer;
1606 layer = t->currentlayers + t->currentnumlayers++;
1608 layer->depthmask = depthmask;
1609 layer->blendfunc1 = blendfunc1;
1610 layer->blendfunc2 = blendfunc2;
1611 layer->texture = texture;
1612 layer->texmatrix = *matrix;
1613 layer->color[0] = r;
1614 layer->color[1] = g;
1615 layer->color[2] = b;
1616 layer->color[3] = a;
1619 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1621 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1622 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1625 texture_t *texture = t;
1626 model_t *model = ent->model;
1627 int s = ent->skinnum;
1628 if ((unsigned int)s >= (unsigned int)model->numskins)
1630 if (model->skinscenes)
1632 if (model->skinscenes[s].framecount > 1)
1633 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1635 s = model->skinscenes[s].firstframe;
1638 t = t + s * model->num_surfaces;
1640 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];
1641 texture->currentframe = t;
1644 t->currentmaterialflags = t->basematerialflags;
1645 t->currentalpha = ent->alpha;
1646 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1647 t->currentalpha *= r_wateralpha.value;
1648 if (!(ent->flags & RENDER_LIGHT))
1649 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1650 if (ent->effects & EF_ADDITIVE)
1651 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1652 else if (t->currentalpha < 1)
1653 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1654 if (ent->effects & EF_NODEPTHTEST)
1655 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1656 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1657 t->currenttexmatrix = r_waterscrollmatrix;
1659 t->currenttexmatrix = r_identitymatrix;
1660 t->currentnumlayers = 0;
1661 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1663 if (gl_lightmaps.integer)
1664 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1665 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1667 // transparent sky would be ridiculous
1668 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1669 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1673 int blendfunc1, blendfunc2, depthmask;
1674 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1676 blendfunc1 = GL_SRC_ALPHA;
1677 blendfunc2 = GL_ONE;
1680 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1682 blendfunc1 = GL_SRC_ALPHA;
1683 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1688 blendfunc1 = GL_ONE;
1689 blendfunc2 = GL_ZERO;
1692 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1694 rtexture_t *currentbasetexture;
1696 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1697 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1698 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
1699 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1701 // fullbright is not affected by r_lightmapintensity
1702 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
1703 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1704 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);
1705 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1706 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);
1712 // q3bsp has no lightmap updates, so the lightstylevalue that
1713 // would normally be baked into the lightmaptexture must be
1714 // applied to the color
1715 if (ent->model->type == mod_brushq3)
1716 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1717 colorscale *= r_lightmapintensity;
1718 if (r_textureunits.integer >= 2 && gl_combine.integer)
1719 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);
1720 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1721 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);
1723 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);
1724 if (r_ambient.value >= (1.0f/64.0f))
1725 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);
1726 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1728 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);
1729 if (r_ambient.value >= (1.0f/64.0f))
1730 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);
1732 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1734 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);
1735 if (r_ambient.value >= (1.0f/64.0f))
1736 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);
1739 if (t->skin.glow != NULL)
1740 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
1741 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1743 // if this is opaque use alpha blend which will darken the earlier
1746 // if this is an alpha blended material, all the earlier passes
1747 // were darkened by fog already, so we only need to add the fog
1748 // color ontop through the fog mask texture
1750 // if this is an additive blended material, all the earlier passes
1751 // were darkened by fog already, and we should not add fog color
1752 // (because the background was not darkened, there is no fog color
1753 // that was lost behind it).
1754 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], t->currentalpha);
1761 void R_UpdateAllTextureInfo(entity_render_t *ent)
1765 for (i = 0;i < ent->model->num_textures;i++)
1766 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1769 float *rsurface_vertex3f;
1770 float *rsurface_svector3f;
1771 float *rsurface_tvector3f;
1772 float *rsurface_normal3f;
1773 float *rsurface_lightmapcolor4f;
1775 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1778 float center[3], forward[3], right[3], up[3], v[4][3];
1779 matrix4x4_t matrix1, imatrix1;
1780 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1782 rsurface_vertex3f = varray_vertex3f;
1783 rsurface_svector3f = NULL;
1784 rsurface_tvector3f = NULL;
1785 rsurface_normal3f = NULL;
1786 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1790 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1791 rsurface_svector3f = surface->groupmesh->data_svector3f;
1792 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1793 rsurface_normal3f = surface->groupmesh->data_normal3f;
1795 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1797 if (!rsurface_svector3f)
1799 rsurface_svector3f = varray_svector3f;
1800 rsurface_tvector3f = varray_tvector3f;
1801 rsurface_normal3f = varray_normal3f;
1802 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);
1804 // a single autosprite surface can contain multiple sprites...
1805 VectorClear(forward);
1807 VectorSet(up, 0, 0, 1);
1808 for (j = 0;j < surface->num_vertices - 3;j += 4)
1810 VectorClear(center);
1811 for (i = 0;i < 4;i++)
1812 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1813 VectorScale(center, 0.25f, center);
1814 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1815 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);
1816 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1817 for (i = 0;i < 4;i++)
1818 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1819 forward[0] = modelorg[0] - center[0];
1820 forward[1] = modelorg[1] - center[1];
1821 VectorNormalize(forward);
1822 right[0] = forward[1];
1823 right[1] = -forward[0];
1824 for (i = 0;i < 4;i++)
1825 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1827 rsurface_vertex3f = varray_vertex3f;
1828 rsurface_svector3f = NULL;
1829 rsurface_tvector3f = NULL;
1830 rsurface_normal3f = NULL;
1832 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1834 if (!rsurface_svector3f)
1836 rsurface_svector3f = varray_svector3f;
1837 rsurface_tvector3f = varray_tvector3f;
1838 rsurface_normal3f = varray_normal3f;
1839 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);
1841 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1842 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1843 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1844 // a single autosprite surface can contain multiple sprites...
1845 for (j = 0;j < surface->num_vertices - 3;j += 4)
1847 VectorClear(center);
1848 for (i = 0;i < 4;i++)
1849 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1850 VectorScale(center, 0.25f, center);
1851 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1852 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);
1853 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1854 for (i = 0;i < 4;i++)
1855 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1856 for (i = 0;i < 4;i++)
1857 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1859 rsurface_vertex3f = varray_vertex3f;
1860 rsurface_svector3f = NULL;
1861 rsurface_tvector3f = NULL;
1862 rsurface_normal3f = NULL;
1864 R_Mesh_VertexPointer(rsurface_vertex3f);
1867 void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
1875 vec4_t ambientcolor4f;
1876 vec3_t diffusecolor;
1877 vec3_t diffusenormal;
1878 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1880 rsurface_lightmapcolor4f = varray_color4f;
1881 if (rsurface_normal3f == NULL)
1883 rsurface_normal3f = varray_normal3f;
1884 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);
1886 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);
1895 r = ambientcolor4f[0];
1896 g = ambientcolor4f[1];
1897 b = ambientcolor4f[2];
1898 a = ambientcolor4f[3];
1899 rsurface_lightmapcolor4f = NULL;
1902 else if (lightmode >= 1)
1904 if (surface->lightmapinfo)
1906 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1908 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1911 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1912 VectorScale(lm, scale, c);
1913 if (surface->lightmapinfo->styles[1] != 255)
1915 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1917 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1918 VectorMA(c, scale, lm, c);
1919 if (surface->lightmapinfo->styles[2] != 255)
1922 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1923 VectorMA(c, scale, lm, c);
1924 if (surface->lightmapinfo->styles[3] != 255)
1927 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1928 VectorMA(c, scale, lm, c);
1936 rsurface_lightmapcolor4f = varray_color4f;
1939 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1942 rsurface_lightmapcolor4f = NULL;
1945 if (rsurface_lightmapcolor4f)
1947 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)
1949 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1958 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)
1960 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1967 rsurface_lightmapcolor4f = varray_color4f;
1969 if (applycolor && rsurface_lightmapcolor4f)
1971 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)
1978 rsurface_lightmapcolor4f = varray_color4f;
1980 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1981 GL_Color(r, g, b, a);
1984 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1986 int texturesurfaceindex;
1988 const msurface_t *surface;
1989 qboolean applycolor;
1991 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1993 renderstats.entities_surfaces += texturenumsurfaces;
1994 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1995 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1996 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1997 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
1998 qglDisable(GL_CULL_FACE);
1999 if (texture->currentnumlayers)
2002 texturelayer_t *layer;
2003 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2006 int layertexrgbscale;
2007 GL_DepthMask(layer->depthmask);
2008 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2009 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2011 layertexrgbscale = 4;
2012 VectorScale(layer->color, 0.25f, layercolor);
2014 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2016 layertexrgbscale = 2;
2017 VectorScale(layer->color, 0.5f, layercolor);
2021 layertexrgbscale = 1;
2022 VectorScale(layer->color, 1.0f, layercolor);
2024 layercolor[3] = layer->color[3];
2025 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2026 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2027 switch (layer->type)
2029 case TEXTURELAYERTYPE_SKY:
2032 skyrendernow = false;
2033 if (skyrendermasked)
2036 // restore entity matrix and GL_Color
2037 R_Mesh_Matrix(&ent->matrix);
2038 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2041 // LordHavoc: HalfLife maps have freaky skypolys...
2042 //if (!ent->model->brush.ishlbsp)
2044 if (skyrendermasked)
2046 // depth-only (masking)
2047 GL_ColorMask(0,0,0,0);
2048 // just to make sure that braindead drivers don't draw anything
2049 // despite that colormask...
2050 GL_BlendFunc(GL_ZERO, GL_ONE);
2055 GL_BlendFunc(GL_ONE, GL_ZERO);
2057 memset(&m, 0, sizeof(m));
2059 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2061 surface = texturesurfacelist[texturesurfaceindex];
2062 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2063 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2064 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2065 GL_LockArrays(0, 0);
2067 if (skyrendermasked)
2068 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2071 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2072 memset(&m, 0, sizeof(m));
2073 m.tex[1] = R_GetTexture(layer->texture);
2074 m.texmatrix[1] = layer->texmatrix;
2075 m.texrgbscale[1] = layertexrgbscale;
2076 m.pointer_color = varray_color4f;
2078 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2080 surface = texturesurfacelist[texturesurfaceindex];
2081 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2082 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2083 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2086 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2087 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2089 else if (surface->lightmaptexture)
2091 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2092 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2096 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2097 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2099 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2100 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2101 GL_LockArrays(0, 0);
2104 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2105 memset(&m, 0, sizeof(m));
2106 m.tex[0] = R_GetTexture(layer->texture);
2107 m.texmatrix[0] = layer->texmatrix;
2108 m.pointer_color = varray_color4f;
2109 m.texrgbscale[0] = layertexrgbscale;
2111 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2113 surface = texturesurfacelist[texturesurfaceindex];
2114 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2115 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2118 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2119 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2121 else if (surface->lightmaptexture)
2123 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2124 R_Mesh_ColorPointer(NULL);
2128 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2129 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2131 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2132 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2133 GL_LockArrays(0, 0);
2135 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2136 memset(&m, 0, sizeof(m));
2137 m.tex[0] = R_GetTexture(layer->texture);
2138 m.texmatrix[0] = layer->texmatrix;
2139 m.pointer_color = varray_color4f;
2140 m.texrgbscale[0] = layertexrgbscale;
2142 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2144 surface = texturesurfacelist[texturesurfaceindex];
2145 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2146 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2147 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2148 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2149 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2150 GL_LockArrays(0, 0);
2153 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2154 memset(&m, 0, sizeof(m));
2155 m.tex[0] = R_GetTexture(layer->texture);
2156 m.texmatrix[0] = layer->texmatrix;
2157 m.texrgbscale[0] = layertexrgbscale;
2158 m.pointer_color = varray_color4f;
2160 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2162 surface = texturesurfacelist[texturesurfaceindex];
2163 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2164 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2165 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2166 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2167 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2168 GL_LockArrays(0, 0);
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 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2182 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2183 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2184 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2185 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2186 GL_LockArrays(0, 0);
2189 case TEXTURELAYERTYPE_FOG:
2190 memset(&m, 0, sizeof(m));
2193 m.tex[0] = R_GetTexture(layer->texture);
2194 m.texmatrix[0] = layer->texmatrix;
2197 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2201 surface = texturesurfacelist[texturesurfaceindex];
2202 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2204 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2205 R_Mesh_ColorPointer(varray_color4f);
2206 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)
2208 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2209 c[0] = layercolor[0];
2210 c[1] = layercolor[1];
2211 c[2] = layercolor[2];
2212 c[3] = f * layercolor[3];
2214 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2215 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2216 GL_LockArrays(0, 0);
2220 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2222 // if trying to do overbright on first pass of an opaque surface
2223 // when combine is not supported, brighten as a post process
2224 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2227 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2228 GL_Color(1, 1, 1, 1);
2229 memset(&m, 0, sizeof(m));
2231 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2233 surface = texturesurfacelist[texturesurfaceindex];
2234 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2235 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2236 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2237 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2238 GL_LockArrays(0, 0);
2242 if (r_shownormals.integer && !r_showtrispass)
2246 GL_DepthTest(!r_showdisabledepthtest.integer);
2247 GL_DepthMask(texture->currentlayers->depthmask);
2248 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
2249 memset(&m, 0, sizeof(m));
2251 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2253 surface = texturesurfacelist[texturesurfaceindex];
2254 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2255 if (!rsurface_svector3f)
2257 rsurface_svector3f = varray_svector3f;
2258 rsurface_tvector3f = varray_tvector3f;
2259 rsurface_normal3f = varray_normal3f;
2260 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);
2262 GL_Color(1, 0, 0, 1);
2264 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2266 VectorCopy(rsurface_vertex3f + k * 3, v);
2267 qglVertex3f(v[0], v[1], v[2]);
2268 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
2269 qglVertex3f(v[0], v[1], v[2]);
2271 GL_Color(0, 0, 1, 1);
2272 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2274 VectorCopy(rsurface_vertex3f + k * 3, v);
2275 qglVertex3f(v[0], v[1], v[2]);
2276 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
2277 qglVertex3f(v[0], v[1], v[2]);
2279 GL_Color(0, 1, 0, 1);
2280 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2282 VectorCopy(rsurface_vertex3f + k * 3, v);
2283 qglVertex3f(v[0], v[1], v[2]);
2284 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
2285 qglVertex3f(v[0], v[1], v[2]);
2291 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2292 qglEnable(GL_CULL_FACE);
2295 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2297 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
2301 texture = surface->texture;
2302 if (texture->basematerialflags & MATERIALFLAG_SKY)
2303 return; // transparent sky is too difficult
2304 R_UpdateTextureInfo(ent, texture);
2306 R_Mesh_Matrix(&ent->matrix);
2307 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2308 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2311 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2313 int texturesurfaceindex;
2314 const msurface_t *surface;
2315 vec3_t tempcenter, center;
2316 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2318 // drawing sky transparently would be too difficult
2319 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2321 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2323 surface = texturesurfacelist[texturesurfaceindex];
2324 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2325 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2326 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2327 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2328 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
2333 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2336 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2337 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2339 int i, j, f, flagsmask;
2340 int counttriangles = 0;
2341 msurface_t *surface, **surfacechain;
2342 texture_t *t, *texture;
2343 model_t *model = ent->model;
2345 const int maxsurfacelist = 1024;
2346 int numsurfacelist = 0;
2347 const msurface_t *surfacelist[1024];
2350 R_Mesh_Matrix(&ent->matrix);
2351 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2353 // update light styles
2354 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2356 for (i = 0;i < model->brushq1.light_styles;i++)
2358 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2360 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2361 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2362 for (;(surface = *surfacechain);surfacechain++)
2363 surface->cached_dlight = true;
2368 R_UpdateAllTextureInfo(ent);
2369 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2374 if (ent == r_refdef.worldentity)
2376 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2378 if (!r_worldsurfacevisible[j])
2380 if (t != surface->texture)
2384 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2387 t = surface->texture;
2388 texture = t->currentframe;
2389 f = texture->currentmaterialflags & flagsmask;
2391 if (f && surface->num_triangles)
2393 // if lightmap parameters changed, rebuild lightmap texture
2394 if (surface->cached_dlight && surface->lightmapinfo->samples)
2395 R_BuildLightMap(ent, surface);
2396 // add face to draw list
2397 surfacelist[numsurfacelist++] = surface;
2398 counttriangles += surface->num_triangles;
2399 if (numsurfacelist >= maxsurfacelist)
2401 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2409 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2411 if (t != surface->texture)
2415 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2418 t = surface->texture;
2419 texture = t->currentframe;
2420 f = texture->currentmaterialflags & flagsmask;
2422 if (f && surface->num_triangles)
2424 // if lightmap parameters changed, rebuild lightmap texture
2425 if (surface->cached_dlight && surface->lightmapinfo->samples)
2426 R_BuildLightMap(ent, surface);
2427 // add face to draw list
2428 surfacelist[numsurfacelist++] = surface;
2429 counttriangles += surface->num_triangles;
2430 if (numsurfacelist >= maxsurfacelist)
2432 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2439 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2440 if (!r_showtrispass)
2441 renderstats.entities_triangles += counttriangles;