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