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_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
74 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
75 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
76 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
77 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
78 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
79 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
80 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
81 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
83 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
84 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
85 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
86 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
87 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
88 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
89 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
91 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)"};
93 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
94 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
95 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
97 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
98 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
99 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
100 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
101 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
103 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"};
105 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"};
107 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
109 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
111 rtexturepool_t *r_main_texturepool;
112 rtexture_t *r_bloom_texture_screen;
113 rtexture_t *r_bloom_texture_bloom;
114 rtexture_t *r_texture_blanknormalmap;
115 rtexture_t *r_texture_white;
116 rtexture_t *r_texture_black;
117 rtexture_t *r_texture_notexture;
118 rtexture_t *r_texture_whitecube;
119 rtexture_t *r_texture_normalizationcube;
120 rtexture_t *r_texture_fogattenuation;
121 rtexture_t *r_texture_fogintensity;
123 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
126 for (i = 0;i < verts;i++)
137 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
140 for (i = 0;i < verts;i++)
155 vec_t fogtabledistmultiplier;
156 float fogtable[FOGTABLEWIDTH];
157 float fog_density, fog_red, fog_green, fog_blue;
159 qboolean oldgl_fogenable;
160 void R_UpdateFog(void)
162 if (gamemode == GAME_NEHAHRA)
164 if (gl_fogenable.integer)
166 oldgl_fogenable = true;
167 fog_density = gl_fogdensity.value;
168 fog_red = gl_fogred.value;
169 fog_green = gl_foggreen.value;
170 fog_blue = gl_fogblue.value;
172 else if (oldgl_fogenable)
174 oldgl_fogenable = false;
183 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
184 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
185 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
190 fogdensity = -4000.0f / (fog_density * fog_density);
191 // this is the point where the fog reaches 0.9986 alpha, which we
192 // consider a good enough cutoff point for the texture
193 // (0.9986 * 256 == 255.6)
194 fogrange = 400 / fog_density;
195 fograngerecip = 1.0f / fogrange;
196 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
197 // fog color was already set
203 // FIXME: move this to client?
206 if (gamemode == GAME_NEHAHRA)
208 Cvar_Set("gl_fogenable", "0");
209 Cvar_Set("gl_fogdensity", "0.2");
210 Cvar_Set("gl_fogred", "0.3");
211 Cvar_Set("gl_foggreen", "0.3");
212 Cvar_Set("gl_fogblue", "0.3");
214 fog_density = fog_red = fog_green = fog_blue = 0.0f;
217 // FIXME: move this to client?
218 void FOG_registercvars(void)
223 if (gamemode == GAME_NEHAHRA)
225 Cvar_RegisterVariable (&gl_fogenable);
226 Cvar_RegisterVariable (&gl_fogdensity);
227 Cvar_RegisterVariable (&gl_fogred);
228 Cvar_RegisterVariable (&gl_foggreen);
229 Cvar_RegisterVariable (&gl_fogblue);
230 Cvar_RegisterVariable (&gl_fogstart);
231 Cvar_RegisterVariable (&gl_fogend);
234 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
235 for (x = 0;x < FOGTABLEWIDTH;x++)
237 alpha = exp(r / ((double)x*(double)x));
238 if (x == FOGTABLEWIDTH - 1)
240 fogtable[x] = bound(0, alpha, 1);
244 static void R_BuildBlankTextures(void)
246 unsigned char data[4];
247 data[0] = 128; // normal X
248 data[1] = 128; // normal Y
249 data[2] = 255; // normal Z
250 data[3] = 128; // height
251 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
256 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
261 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
264 static void R_BuildNoTexture(void)
267 unsigned char pix[16][16][4];
268 // this makes a light grey/dark grey checkerboard texture
269 for (y = 0;y < 16;y++)
271 for (x = 0;x < 16;x++)
273 if ((y < 8) ^ (x < 8))
289 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
292 static void R_BuildWhiteCube(void)
294 unsigned char data[6*1*1*4];
295 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
296 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
297 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
298 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
299 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
300 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
301 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
304 static void R_BuildNormalizationCube(void)
308 vec_t s, t, intensity;
310 unsigned char data[6][NORMSIZE][NORMSIZE][4];
311 for (side = 0;side < 6;side++)
313 for (y = 0;y < NORMSIZE;y++)
315 for (x = 0;x < NORMSIZE;x++)
317 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
318 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
353 intensity = 127.0f / sqrt(DotProduct(v, v));
354 data[side][y][x][0] = 128.0f + intensity * v[0];
355 data[side][y][x][1] = 128.0f + intensity * v[1];
356 data[side][y][x][2] = 128.0f + intensity * v[2];
357 data[side][y][x][3] = 255;
361 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
364 static void R_BuildFogTexture(void)
369 unsigned char data1[FOGWIDTH][4];
370 unsigned char data2[FOGWIDTH][4];
371 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
372 for (x = 0;x < FOGWIDTH;x++)
374 alpha = exp(r / ((double)x*(double)x));
375 if (x == FOGWIDTH - 1)
377 b = (int)(256.0 * alpha);
378 b = bound(0, b, 255);
379 data1[x][0] = 255 - b;
380 data1[x][1] = 255 - b;
381 data1[x][2] = 255 - b;
388 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
389 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
392 void gl_main_start(void)
394 r_main_texturepool = R_AllocTexturePool();
395 r_bloom_texture_screen = NULL;
396 r_bloom_texture_bloom = NULL;
397 R_BuildBlankTextures();
399 if (gl_texturecubemap)
402 R_BuildNormalizationCube();
407 void gl_main_shutdown(void)
409 R_FreeTexturePool(&r_main_texturepool);
410 r_bloom_texture_screen = NULL;
411 r_bloom_texture_bloom = NULL;
412 r_texture_blanknormalmap = NULL;
413 r_texture_white = NULL;
414 r_texture_black = NULL;
415 r_texture_whitecube = NULL;
416 r_texture_normalizationcube = NULL;
419 extern void CL_ParseEntityLump(char *entitystring);
420 void gl_main_newmap(void)
422 // FIXME: move this code to client
424 char *entities, entname[MAX_QPATH];
428 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
429 l = (int)strlen(entname) - 4;
430 if (l >= 0 && !strcmp(entname + l, ".bsp"))
432 strcpy(entname + l, ".ent");
433 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
435 CL_ParseEntityLump(entities);
440 if (cl.worldmodel->brush.entities)
441 CL_ParseEntityLump(cl.worldmodel->brush.entities);
445 void GL_Main_Init(void)
447 Matrix4x4_CreateIdentity(&r_identitymatrix);
448 // FIXME: move this to client?
450 Cvar_RegisterVariable(&r_showtris);
451 Cvar_RegisterVariable(&r_shownormals);
452 Cvar_RegisterVariable(&r_drawentities);
453 Cvar_RegisterVariable(&r_drawviewmodel);
454 Cvar_RegisterVariable(&r_speeds);
455 Cvar_RegisterVariable(&r_fullbrights);
456 Cvar_RegisterVariable(&r_wateralpha);
457 Cvar_RegisterVariable(&r_dynamic);
458 Cvar_RegisterVariable(&r_fullbright);
459 Cvar_RegisterVariable(&r_textureunits);
460 Cvar_RegisterVariable(&r_lerpsprites);
461 Cvar_RegisterVariable(&r_lerpmodels);
462 Cvar_RegisterVariable(&r_waterscroll);
463 Cvar_RegisterVariable(&r_drawcollisionbrushes);
464 Cvar_RegisterVariable(&r_bloom);
465 Cvar_RegisterVariable(&r_bloom_intensity);
466 Cvar_RegisterVariable(&r_bloom_blur);
467 Cvar_RegisterVariable(&r_bloom_resolution);
468 Cvar_RegisterVariable(&r_bloom_power);
469 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
470 Cvar_RegisterVariable(&developer_texturelogging);
471 Cvar_RegisterVariable(&gl_lightmaps);
472 Cvar_RegisterVariable(&r_test);
473 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
474 Cvar_SetValue("r_fullbrights", 0);
475 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
478 static vec3_t r_farclip_origin;
479 static vec3_t r_farclip_direction;
480 static vec_t r_farclip_directiondist;
481 static vec_t r_farclip_meshfarclip;
482 static int r_farclip_directionbit0;
483 static int r_farclip_directionbit1;
484 static int r_farclip_directionbit2;
486 // enlarge farclip to accomodate box
487 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
490 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
491 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
492 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
493 if (r_farclip_meshfarclip < d)
494 r_farclip_meshfarclip = d;
497 // return farclip value
498 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
502 VectorCopy(origin, r_farclip_origin);
503 VectorCopy(direction, r_farclip_direction);
504 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
505 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
506 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
507 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
508 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
510 if (r_refdef.worldmodel)
511 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
512 for (i = 0;i < r_refdef.numentities;i++)
513 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
515 return r_farclip_meshfarclip - r_farclip_directiondist;
518 extern void R_Textures_Init(void);
519 extern void GL_Draw_Init(void);
520 extern void GL_Main_Init(void);
521 extern void R_Shadow_Init(void);
522 extern void R_Sky_Init(void);
523 extern void GL_Surf_Init(void);
524 extern void R_Crosshairs_Init(void);
525 extern void R_Light_Init(void);
526 extern void R_Particles_Init(void);
527 extern void R_Explosion_Init(void);
528 extern void gl_backend_init(void);
529 extern void Sbar_Init(void);
530 extern void R_LightningBeams_Init(void);
531 extern void Mod_RenderInit(void);
533 void Render_Init(void)
549 R_LightningBeams_Init();
558 extern char *ENGINE_EXTENSIONS;
561 VID_CheckExtensions();
563 // LordHavoc: report supported extensions
564 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
566 // clear to black (loading plaque will be seen over this)
567 qglClearColor(0,0,0,1);
568 qglClear(GL_COLOR_BUFFER_BIT);
571 int R_CullBox(const vec3_t mins, const vec3_t maxs)
575 for (i = 0;i < 4;i++)
582 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
586 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
590 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
594 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
598 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
602 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
606 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
610 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
618 //==================================================================================
620 static void R_MarkEntities (void)
623 entity_render_t *ent;
625 if (!r_drawentities.integer)
628 r_refdef.worldentity->visframe = r_framecount;
629 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
630 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
632 // worldmodel can check visibility
633 for (i = 0;i < r_refdef.numentities;i++)
635 ent = r_refdef.entities[i];
636 // some of the renderer still relies on origin...
637 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
638 // some of the renderer still relies on scale...
639 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
640 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)))
642 R_UpdateEntLights(ent);
643 ent->visframe = r_framecount;
649 // no worldmodel or it can't check visibility
650 for (i = 0;i < r_refdef.numentities;i++)
652 ent = r_refdef.entities[i];
653 // some of the renderer still relies on origin...
654 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
655 // some of the renderer still relies on scale...
656 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
657 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
659 R_UpdateEntLights(ent);
660 ent->visframe = r_framecount;
666 // only used if skyrendermasked, and normally returns false
667 int R_DrawBrushModelsSky (void)
670 entity_render_t *ent;
672 if (!r_drawentities.integer)
676 for (i = 0;i < r_refdef.numentities;i++)
678 ent = r_refdef.entities[i];
679 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
681 ent->model->DrawSky(ent);
688 void R_DrawNoModel(entity_render_t *ent);
689 void R_DrawModels(void)
692 entity_render_t *ent;
694 if (!r_drawentities.integer)
697 for (i = 0;i < r_refdef.numentities;i++)
699 ent = r_refdef.entities[i];
700 if (ent->visframe == r_framecount)
702 renderstats.entities++;
703 if (ent->model && ent->model->Draw != NULL)
704 ent->model->Draw(ent);
711 static void R_SetFrustum(void)
713 // break apart the view matrix into vectors for various purposes
714 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
715 VectorNegate(r_viewleft, r_viewright);
718 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
719 frustum[0].normal[1] = 0 - 0;
720 frustum[0].normal[2] = -1 - 0;
721 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
722 frustum[1].normal[1] = 0 + 0;
723 frustum[1].normal[2] = -1 + 0;
724 frustum[2].normal[0] = 0 - 0;
725 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
726 frustum[2].normal[2] = -1 - 0;
727 frustum[3].normal[0] = 0 + 0;
728 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
729 frustum[3].normal[2] = -1 + 0;
734 nudge = 1.0 - 1.0 / (1<<23);
735 frustum[4].normal[0] = 0 - 0;
736 frustum[4].normal[1] = 0 - 0;
737 frustum[4].normal[2] = -1 - -nudge;
738 frustum[4].dist = 0 - -2 * zNear * nudge;
739 frustum[5].normal[0] = 0 + 0;
740 frustum[5].normal[1] = 0 + 0;
741 frustum[5].normal[2] = -1 + -nudge;
742 frustum[5].dist = 0 + -2 * zNear * nudge;
748 frustum[0].normal[0] = m[3] - m[0];
749 frustum[0].normal[1] = m[7] - m[4];
750 frustum[0].normal[2] = m[11] - m[8];
751 frustum[0].dist = m[15] - m[12];
753 frustum[1].normal[0] = m[3] + m[0];
754 frustum[1].normal[1] = m[7] + m[4];
755 frustum[1].normal[2] = m[11] + m[8];
756 frustum[1].dist = m[15] + m[12];
758 frustum[2].normal[0] = m[3] - m[1];
759 frustum[2].normal[1] = m[7] - m[5];
760 frustum[2].normal[2] = m[11] - m[9];
761 frustum[2].dist = m[15] - m[13];
763 frustum[3].normal[0] = m[3] + m[1];
764 frustum[3].normal[1] = m[7] + m[5];
765 frustum[3].normal[2] = m[11] + m[9];
766 frustum[3].dist = m[15] + m[13];
768 frustum[4].normal[0] = m[3] - m[2];
769 frustum[4].normal[1] = m[7] - m[6];
770 frustum[4].normal[2] = m[11] - m[10];
771 frustum[4].dist = m[15] - m[14];
773 frustum[5].normal[0] = m[3] + m[2];
774 frustum[5].normal[1] = m[7] + m[6];
775 frustum[5].normal[2] = m[11] + m[10];
776 frustum[5].dist = m[15] + m[14];
781 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
782 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
783 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
784 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
785 VectorCopy(r_viewforward, frustum[4].normal);
786 VectorNormalize(frustum[0].normal);
787 VectorNormalize(frustum[1].normal);
788 VectorNormalize(frustum[2].normal);
789 VectorNormalize(frustum[3].normal);
790 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
791 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
792 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
793 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
794 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
795 PlaneClassify(&frustum[0]);
796 PlaneClassify(&frustum[1]);
797 PlaneClassify(&frustum[2]);
798 PlaneClassify(&frustum[3]);
799 PlaneClassify(&frustum[4]);
801 // LordHavoc: note to all quake engine coders, Quake had a special case
802 // for 90 degrees which assumed a square view (wrong), so I removed it,
803 // Quake2 has it disabled as well.
805 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
806 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
807 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
808 //PlaneClassify(&frustum[0]);
810 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
811 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
812 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
813 //PlaneClassify(&frustum[1]);
815 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
816 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
817 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
818 //PlaneClassify(&frustum[2]);
820 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
821 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
822 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
823 //PlaneClassify(&frustum[3]);
826 //VectorCopy(r_viewforward, frustum[4].normal);
827 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
828 //PlaneClassify(&frustum[4]);
831 static void R_BlendView(void)
833 int screenwidth, screenheight;
838 // set the (poorly named) screenwidth and screenheight variables to
839 // a power of 2 at least as large as the screen, these will define the
840 // size of the texture to allocate
841 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
842 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
844 doblend = r_refdef.viewblend[3] >= 0.01f;
845 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;
847 if (!dobloom && !doblend)
850 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
853 R_Mesh_Matrix(&r_identitymatrix);
854 // vertex coordinates for a quad that covers the screen exactly
855 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
856 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
857 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
858 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
861 int bloomwidth, bloomheight, x, dobloomblend, range;
862 float xoffset, yoffset, r;
864 // allocate textures as needed
865 if (!r_bloom_texture_screen)
866 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
867 if (!r_bloom_texture_bloom)
868 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
869 // set bloomwidth and bloomheight to the bloom resolution that will be
870 // used (often less than the screen resolution for faster rendering)
871 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
872 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
873 // set up a texcoord array for the full resolution screen image
874 // (we have to keep this around to copy back during final render)
875 varray_texcoord2f[0][0] = 0;
876 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
877 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
878 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
879 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
880 varray_texcoord2f[0][5] = 0;
881 varray_texcoord2f[0][6] = 0;
882 varray_texcoord2f[0][7] = 0;
883 // set up a texcoord array for the reduced resolution bloom image
884 // (which will be additive blended over the screen image)
885 varray_texcoord2f[1][0] = 0;
886 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
887 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
888 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
889 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
890 varray_texcoord2f[1][5] = 0;
891 varray_texcoord2f[1][6] = 0;
892 varray_texcoord2f[1][7] = 0;
893 memset(&m, 0, sizeof(m));
894 m.pointer_vertex = varray_vertex3f;
895 m.pointer_texcoord[0] = varray_texcoord2f[0];
896 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
898 // copy view into the full resolution screen image texture
900 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
901 renderstats.bloom_copypixels += r_view_width * r_view_height;
902 // now scale it down to the bloom size and raise to a power of itself
903 // to darken it (this leaves the really bright stuff bright, and
904 // everything else becomes very dark)
905 // TODO: optimize with multitexture or GLSL
906 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
907 GL_BlendFunc(GL_ONE, GL_ZERO);
908 GL_Color(1, 1, 1, 1);
909 R_Mesh_Draw(0, 4, 2, polygonelements);
910 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
911 // render multiple times with a multiply blendfunc to raise to a power
912 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
913 for (x = 1;x < r_bloom_power.integer;x++)
915 R_Mesh_Draw(0, 4, 2, polygonelements);
916 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
918 // we now have a darkened bloom image in the framebuffer, copy it into
919 // the bloom image texture for more processing
920 memset(&m, 0, sizeof(m));
921 m.pointer_vertex = varray_vertex3f;
922 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
923 m.pointer_texcoord[0] = varray_texcoord2f[2];
926 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
927 renderstats.bloom_copypixels += bloomwidth * bloomheight;
928 // blend on at multiple vertical offsets to achieve a vertical blur
929 // TODO: do offset blends using GLSL
930 range = r_bloom_blur.integer * bloomwidth / 320;
931 GL_BlendFunc(GL_ONE, GL_ZERO);
932 for (x = -range;x <= range;x++)
934 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
935 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
936 // compute a texcoord array with the specified x and y offset
937 varray_texcoord2f[2][0] = xoffset+0;
938 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
939 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
940 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
941 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
942 varray_texcoord2f[2][5] = yoffset+0;
943 varray_texcoord2f[2][6] = xoffset+0;
944 varray_texcoord2f[2][7] = yoffset+0;
945 // this r value looks like a 'dot' particle, fading sharply to
946 // black at the edges
947 // (probably not realistic but looks good enough)
948 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
951 GL_Color(r, r, r, 1);
952 R_Mesh_Draw(0, 4, 2, polygonelements);
953 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
954 GL_BlendFunc(GL_ONE, GL_ONE);
956 // copy the vertically blurred bloom view to a texture
958 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
959 renderstats.bloom_copypixels += bloomwidth * bloomheight;
960 // blend the vertically blurred image at multiple offsets horizontally
961 // to finish the blur effect
962 // TODO: do offset blends using GLSL
963 range = r_bloom_blur.integer * bloomwidth / 320;
964 GL_BlendFunc(GL_ONE, GL_ZERO);
965 for (x = -range;x <= range;x++)
967 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
968 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
969 // compute a texcoord array with the specified x and y offset
970 varray_texcoord2f[2][0] = xoffset+0;
971 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
972 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
973 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
974 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
975 varray_texcoord2f[2][5] = yoffset+0;
976 varray_texcoord2f[2][6] = xoffset+0;
977 varray_texcoord2f[2][7] = yoffset+0;
978 // this r value looks like a 'dot' particle, fading sharply to
979 // black at the edges
980 // (probably not realistic but looks good enough)
981 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
984 GL_Color(r, r, r, 1);
985 R_Mesh_Draw(0, 4, 2, polygonelements);
986 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
987 GL_BlendFunc(GL_ONE, GL_ONE);
989 // copy the blurred bloom view to a texture
991 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
992 renderstats.bloom_copypixels += bloomwidth * bloomheight;
993 // go back to full view area
994 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
995 // put the original screen image back in place and blend the bloom
997 memset(&m, 0, sizeof(m));
998 m.pointer_vertex = varray_vertex3f;
999 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1000 m.pointer_texcoord[0] = varray_texcoord2f[0];
1002 dobloomblend = false;
1004 // do both in one pass if possible
1005 if (r_textureunits.integer >= 2 && gl_combine.integer)
1007 dobloomblend = false;
1008 m.texcombinergb[1] = GL_ADD;
1009 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1010 m.pointer_texcoord[1] = varray_texcoord2f[1];
1013 dobloomblend = true;
1016 GL_BlendFunc(GL_ONE, GL_ZERO);
1018 R_Mesh_Draw(0, 4, 2, polygonelements);
1019 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1020 // now blend on the bloom texture if multipass
1023 memset(&m, 0, sizeof(m));
1024 m.pointer_vertex = varray_vertex3f;
1025 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1026 m.pointer_texcoord[0] = varray_texcoord2f[1];
1028 GL_BlendFunc(GL_ONE, GL_ONE);
1030 R_Mesh_Draw(0, 4, 2, polygonelements);
1031 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1036 // apply a color tint to the whole view
1037 memset(&m, 0, sizeof(m));
1038 m.pointer_vertex = varray_vertex3f;
1040 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1041 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1042 R_Mesh_Draw(0, 4, 2, polygonelements);
1046 void R_RenderScene(void);
1048 matrix4x4_t r_waterscrollmatrix;
1055 void R_RenderView(void)
1057 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1058 return; //Host_Error ("R_RenderView: NULL worldmodel");
1060 r_view_width = bound(0, r_refdef.width, vid.width);
1061 r_view_height = bound(0, r_refdef.height, vid.height);
1063 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1064 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1066 r_view_matrix = r_refdef.viewentitymatrix;
1067 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1068 r_rtworld = r_shadow_realtime_world.integer;
1069 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1070 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1071 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1072 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1074 // GL is weird because it's bottom to top, r_view_y is top to bottom
1075 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1076 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1077 GL_ScissorTest(true);
1082 R_TimeReport("setup");
1084 qglDepthFunc(GL_LEQUAL);
1085 qglPolygonOffset(0, 0);
1086 qglEnable(GL_POLYGON_OFFSET_FILL);
1090 qglPolygonOffset(0, 0);
1091 qglDisable(GL_POLYGON_OFFSET_FILL);
1094 R_TimeReport("blendview");
1096 GL_Scissor(0, 0, vid.width, vid.height);
1097 GL_ScissorTest(false);
1101 void CSQC_R_ClearScreen (void)
1103 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1104 return; //Host_Error ("R_RenderView: NULL worldmodel");
1106 r_view_width = bound(0, r_refdef.width, vid.width);
1107 r_view_height = bound(0, r_refdef.height, vid.height);
1109 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1110 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1112 r_view_matrix = r_refdef.viewentitymatrix;
1113 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1114 r_rtworld = r_shadow_realtime_world.integer;
1115 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1116 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1117 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1118 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1120 // GL is weird because it's bottom to top, r_view_y is top to bottom
1121 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1122 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1123 GL_ScissorTest(true);
1128 R_TimeReport("setup");
1132 void CSQC_R_RenderScene (void)
1134 qglDepthFunc(GL_LEQUAL);
1135 qglPolygonOffset(0, 0);
1136 qglEnable(GL_POLYGON_OFFSET_FILL);
1140 qglPolygonOffset(0, 0);
1141 qglDisable(GL_POLYGON_OFFSET_FILL);
1144 R_TimeReport("blendview");
1146 GL_Scissor(0, 0, vid.width, vid.height);
1147 GL_ScissorTest(false);
1150 extern void R_DrawLightningBeams (void);
1151 extern void VM_AddPolygonsToMeshQueue (void);
1152 void R_RenderScene(void)
1154 // don't let sound skip if going slow
1155 if (r_refdef.extraupdate)
1160 R_MeshQueue_BeginScene();
1162 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1166 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1167 if (r_rtworldshadows || r_rtdlightshadows)
1168 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f);
1170 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, 1.0f, r_farclip);
1172 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1174 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);
1178 R_WorldVisibility();
1179 R_TimeReport("worldvis");
1182 R_TimeReport("markentity");
1184 R_Shadow_UpdateWorldLightSelection();
1186 // don't let sound skip if going slow
1187 if (r_refdef.extraupdate)
1190 if (cl.csqc_vidvars.drawworld)
1192 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1193 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1195 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1196 R_TimeReport("worldsky");
1199 if (R_DrawBrushModelsSky())
1200 R_TimeReport("bmodelsky");
1202 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1203 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1205 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1206 R_TimeReport("world");
1210 // don't let sound skip if going slow
1211 if (r_refdef.extraupdate)
1214 GL_ShowTrisColor(0, 0.015, 0, 1);
1217 R_TimeReport("models");
1219 // don't let sound skip if going slow
1220 if (r_refdef.extraupdate)
1223 GL_ShowTrisColor(0, 0, 0.033, 1);
1224 R_ShadowVolumeLighting(false);
1225 R_TimeReport("rtlights");
1227 // don't let sound skip if going slow
1228 if (r_refdef.extraupdate)
1231 GL_ShowTrisColor(0.1, 0, 0, 1);
1233 if (cl.csqc_vidvars.drawworld)
1235 R_DrawLightningBeams();
1236 R_TimeReport("lightning");
1239 R_TimeReport("particles");
1242 R_TimeReport("explosions");
1245 R_MeshQueue_RenderTransparent();
1246 R_TimeReport("drawtrans");
1248 if (cl.csqc_vidvars.drawworld)
1251 R_TimeReport("coronas");
1253 if(cl.csqc_vidvars.drawcrosshair)
1255 R_DrawWorldCrosshair();
1256 R_TimeReport("crosshair");
1259 VM_AddPolygonsToMeshQueue();
1261 R_MeshQueue_Render();
1262 R_MeshQueue_EndScene();
1264 if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1266 R_ShadowVolumeLighting(true);
1267 R_TimeReport("visiblevolume");
1270 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1272 // don't let sound skip if going slow
1273 if (r_refdef.extraupdate)
1278 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1281 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1283 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1284 GL_DepthMask(false);
1286 R_Mesh_Matrix(&r_identitymatrix);
1288 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1289 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1290 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1291 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1292 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1293 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1294 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1295 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1296 R_FillColors(color, 8, cr, cg, cb, ca);
1299 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1301 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1303 c[0] = c[0] * f1 + fogcolor[0] * f2;
1304 c[1] = c[1] * f1 + fogcolor[1] * f2;
1305 c[2] = c[2] * f1 + fogcolor[2] * f2;
1308 memset(&m, 0, sizeof(m));
1309 m.pointer_vertex = vertex3f;
1310 m.pointer_color = color;
1316 int nomodelelements[24] =
1328 float nomodelvertex3f[6*3] =
1338 float nomodelcolor4f[6*4] =
1340 0.0f, 0.0f, 0.5f, 1.0f,
1341 0.0f, 0.0f, 0.5f, 1.0f,
1342 0.0f, 0.5f, 0.0f, 1.0f,
1343 0.0f, 0.5f, 0.0f, 1.0f,
1344 0.5f, 0.0f, 0.0f, 1.0f,
1345 0.5f, 0.0f, 0.0f, 1.0f
1348 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
1354 R_Mesh_Matrix(&ent->matrix);
1356 memset(&m, 0, sizeof(m));
1357 m.pointer_vertex = nomodelvertex3f;
1359 if (ent->flags & EF_ADDITIVE)
1361 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1362 GL_DepthMask(false);
1364 else if (ent->alpha < 1)
1366 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1367 GL_DepthMask(false);
1371 GL_BlendFunc(GL_ONE, GL_ZERO);
1374 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1377 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1378 m.pointer_color = color4f;
1379 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1381 for (i = 0, c = color4f;i < 6;i++, c += 4)
1383 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1384 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1385 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1389 else if (ent->alpha != 1)
1391 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1392 m.pointer_color = color4f;
1393 for (i = 0, c = color4f;i < 6;i++, c += 4)
1397 m.pointer_color = nomodelcolor4f;
1399 R_Mesh_Draw(0, 6, 8, nomodelelements);
1402 void R_DrawNoModel(entity_render_t *ent)
1404 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1405 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1407 // R_DrawNoModelCallback(ent, 0);
1410 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1412 vec3_t right1, right2, diff, normal;
1414 VectorSubtract (org2, org1, normal);
1416 // calculate 'right' vector for start
1417 VectorSubtract (r_vieworigin, org1, diff);
1418 CrossProduct (normal, diff, right1);
1419 VectorNormalize (right1);
1421 // calculate 'right' vector for end
1422 VectorSubtract (r_vieworigin, org2, diff);
1423 CrossProduct (normal, diff, right2);
1424 VectorNormalize (right2);
1426 vert[ 0] = org1[0] + width * right1[0];
1427 vert[ 1] = org1[1] + width * right1[1];
1428 vert[ 2] = org1[2] + width * right1[2];
1429 vert[ 3] = org1[0] - width * right1[0];
1430 vert[ 4] = org1[1] - width * right1[1];
1431 vert[ 5] = org1[2] - width * right1[2];
1432 vert[ 6] = org2[0] - width * right2[0];
1433 vert[ 7] = org2[1] - width * right2[1];
1434 vert[ 8] = org2[2] - width * right2[2];
1435 vert[ 9] = org2[0] + width * right2[0];
1436 vert[10] = org2[1] + width * right2[1];
1437 vert[11] = org2[2] + width * right2[2];
1440 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1442 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)
1444 float fog = 0.0f, ifog;
1448 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1451 R_Mesh_Matrix(&r_identitymatrix);
1452 GL_BlendFunc(blendfunc1, blendfunc2);
1453 GL_DepthMask(false);
1454 GL_DepthTest(!depthdisable);
1456 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1457 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1458 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1459 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1460 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1461 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1462 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1463 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1464 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1465 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1466 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1467 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1469 memset(&m, 0, sizeof(m));
1470 m.tex[0] = R_GetTexture(texture);
1471 m.pointer_texcoord[0] = spritetexcoord2f;
1472 m.pointer_vertex = varray_vertex3f;
1474 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
1475 R_Mesh_Draw(0, 4, 2, polygonelements);
1477 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
1479 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
1480 GL_BlendFunc(blendfunc1, GL_ONE);
1481 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
1482 R_Mesh_Draw(0, 4, 2, polygonelements);
1486 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1490 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1491 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1493 if (i == mesh->numvertices)
1495 if (mesh->numvertices < mesh->maxvertices)
1497 VectorCopy(v, vertex3f);
1498 mesh->numvertices++;
1500 return mesh->numvertices;
1506 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1510 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1511 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1512 e = mesh->element3i + mesh->numtriangles * 3;
1513 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1515 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1516 if (mesh->numtriangles < mesh->maxtriangles)
1521 mesh->numtriangles++;
1523 element[1] = element[2];
1527 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1529 int planenum, planenum2;
1532 mplane_t *plane, *plane2;
1533 float temppoints[2][256*3];
1534 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1538 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1539 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1541 if (planenum2 == planenum)
1543 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);
1546 if (tempnumpoints < 3)
1548 // generate elements forming a triangle fan for this polygon
1549 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1553 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)
1555 texturelayer_t *layer;
1556 layer = t->currentlayers + t->currentnumlayers++;
1558 layer->depthmask = depthmask;
1559 layer->blendfunc1 = blendfunc1;
1560 layer->blendfunc2 = blendfunc2;
1561 layer->texture = texture;
1562 layer->texmatrix = *matrix;
1563 layer->color[0] = r;
1564 layer->color[1] = g;
1565 layer->color[2] = b;
1566 layer->color[3] = a;
1569 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1571 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1572 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1575 texture_t *texture = t;
1576 model_t *model = ent->model;
1577 int s = ent->skinnum;
1578 if ((unsigned int)s >= (unsigned int)model->numskins)
1580 if (model->skinscenes)
1582 if (model->skinscenes[s].framecount > 1)
1583 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1585 s = model->skinscenes[s].firstframe;
1588 t = t + s * model->num_surfaces;
1590 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];
1591 texture->currentframe = t;
1594 t->currentmaterialflags = t->basematerialflags;
1595 t->currentalpha = ent->alpha;
1596 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1597 t->currentalpha *= r_wateralpha.value;
1598 if (!(ent->flags & RENDER_LIGHT))
1599 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1600 if (ent->effects & EF_ADDITIVE)
1601 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1602 else if (t->currentalpha < 1)
1603 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1604 if (ent->effects & EF_NODEPTHTEST)
1605 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1606 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1607 t->currenttexmatrix = r_waterscrollmatrix;
1609 t->currenttexmatrix = r_identitymatrix;
1610 t->currentnumlayers = 0;
1611 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1613 if (gl_lightmaps.integer)
1614 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1615 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1617 // transparent sky would be ridiculous
1618 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1619 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1623 int blendfunc1, blendfunc2, depthmask;
1624 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1626 blendfunc1 = GL_SRC_ALPHA;
1627 blendfunc2 = GL_ONE;
1630 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1632 blendfunc1 = GL_SRC_ALPHA;
1633 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1638 blendfunc1 = GL_ONE;
1639 blendfunc2 = GL_ZERO;
1642 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1644 rtexture_t *currentbasetexture;
1646 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1647 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1648 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
1649 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1651 // fullbright is not affected by r_lightmapintensity
1652 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
1653 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1654 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);
1655 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1656 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);
1662 // q3bsp has no lightmap updates, so the lightstylevalue that
1663 // would normally be baked into the lightmaptexture must be
1664 // applied to the color
1665 if (ent->model->type == mod_brushq3)
1666 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1667 colorscale *= r_lightmapintensity;
1668 if (r_textureunits.integer >= 2 && gl_combine.integer)
1669 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);
1670 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1671 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);
1673 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);
1674 if (r_ambient.value >= (1.0f/64.0f))
1675 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);
1676 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
1678 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);
1679 if (r_ambient.value >= (1.0f/64.0f))
1680 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);
1682 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
1684 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);
1685 if (r_ambient.value >= (1.0f/64.0f))
1686 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);
1689 if (t->skin.glow != NULL)
1690 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
1691 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1693 // if this is opaque use alpha blend which will darken the earlier
1696 // if this is an alpha blended material, all the earlier passes
1697 // were darkened by fog already, so we only need to add the fog
1698 // color ontop through the fog mask texture
1700 // if this is an additive blended material, all the earlier passes
1701 // were darkened by fog already, and we should not add fog color
1702 // (because the background was not darkened, there is no fog color
1703 // that was lost behind it).
1704 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);
1711 void R_UpdateAllTextureInfo(entity_render_t *ent)
1715 for (i = 0;i < ent->model->num_textures;i++)
1716 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1719 float *rsurface_vertex3f;
1720 float *rsurface_svector3f;
1721 float *rsurface_tvector3f;
1722 float *rsurface_normal3f;
1723 float *rsurface_lightmapcolor4f;
1725 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1728 float center[3], forward[3], right[3], up[3], v[4][3];
1729 matrix4x4_t matrix1, imatrix1;
1730 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1732 rsurface_vertex3f = varray_vertex3f;
1733 rsurface_svector3f = NULL;
1734 rsurface_tvector3f = NULL;
1735 rsurface_normal3f = NULL;
1736 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1740 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1741 rsurface_svector3f = surface->groupmesh->data_svector3f;
1742 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1743 rsurface_normal3f = surface->groupmesh->data_normal3f;
1745 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1747 if (!rsurface_svector3f)
1749 rsurface_svector3f = varray_svector3f;
1750 rsurface_tvector3f = varray_tvector3f;
1751 rsurface_normal3f = varray_normal3f;
1752 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);
1754 // a single autosprite surface can contain multiple sprites...
1755 VectorClear(forward);
1757 VectorSet(up, 0, 0, 1);
1758 for (j = 0;j < surface->num_vertices - 3;j += 4)
1760 VectorClear(center);
1761 for (i = 0;i < 4;i++)
1762 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1763 VectorScale(center, 0.25f, center);
1764 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1765 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);
1766 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1767 for (i = 0;i < 4;i++)
1768 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1769 forward[0] = modelorg[0] - center[0];
1770 forward[1] = modelorg[1] - center[1];
1771 VectorNormalize(forward);
1772 right[0] = forward[1];
1773 right[1] = -forward[0];
1774 for (i = 0;i < 4;i++)
1775 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1777 rsurface_vertex3f = varray_vertex3f;
1778 rsurface_svector3f = NULL;
1779 rsurface_tvector3f = NULL;
1780 rsurface_normal3f = NULL;
1782 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1784 if (!rsurface_svector3f)
1786 rsurface_svector3f = varray_svector3f;
1787 rsurface_tvector3f = varray_tvector3f;
1788 rsurface_normal3f = varray_normal3f;
1789 Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
1791 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1792 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1793 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1794 // a single autosprite surface can contain multiple sprites...
1795 for (j = 0;j < surface->num_vertices - 3;j += 4)
1797 VectorClear(center);
1798 for (i = 0;i < 4;i++)
1799 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1800 VectorScale(center, 0.25f, center);
1801 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1802 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);
1803 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1804 for (i = 0;i < 4;i++)
1805 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1806 for (i = 0;i < 4;i++)
1807 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1809 rsurface_vertex3f = varray_vertex3f;
1810 rsurface_svector3f = NULL;
1811 rsurface_tvector3f = NULL;
1812 rsurface_normal3f = NULL;
1814 R_Mesh_VertexPointer(rsurface_vertex3f);
1817 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)
1825 vec4_t ambientcolor4f;
1826 vec3_t diffusecolor;
1827 vec3_t diffusenormal;
1828 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1830 rsurface_lightmapcolor4f = varray_color4f;
1831 if (rsurface_normal3f == NULL)
1833 rsurface_normal3f = varray_normal3f;
1834 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);
1836 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);
1845 r = ambientcolor4f[0];
1846 g = ambientcolor4f[1];
1847 b = ambientcolor4f[2];
1848 a = ambientcolor4f[3];
1849 rsurface_lightmapcolor4f = NULL;
1852 else if (lightmode >= 1)
1854 if (surface->lightmapinfo)
1856 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1858 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1861 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1862 VectorScale(lm, scale, c);
1863 if (surface->lightmapinfo->styles[1] != 255)
1865 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1867 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1868 VectorMA(c, scale, lm, c);
1869 if (surface->lightmapinfo->styles[2] != 255)
1872 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1873 VectorMA(c, scale, lm, c);
1874 if (surface->lightmapinfo->styles[3] != 255)
1877 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1878 VectorMA(c, scale, lm, c);
1886 rsurface_lightmapcolor4f = varray_color4f;
1889 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1892 rsurface_lightmapcolor4f = NULL;
1895 if (rsurface_lightmapcolor4f)
1897 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)
1899 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1908 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)
1910 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1917 rsurface_lightmapcolor4f = varray_color4f;
1919 if (applycolor && rsurface_lightmapcolor4f)
1921 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)
1928 rsurface_lightmapcolor4f = varray_color4f;
1930 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1931 GL_Color(r, g, b, a);
1934 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1936 int texturesurfaceindex;
1938 const msurface_t *surface;
1939 qboolean applycolor;
1941 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1943 renderstats.entities_surfaces += texturenumsurfaces;
1944 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1945 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1946 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1947 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
1948 qglDisable(GL_CULL_FACE);
1949 if (texture->currentnumlayers)
1952 texturelayer_t *layer;
1953 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1956 int layertexrgbscale;
1957 GL_DepthMask(layer->depthmask);
1958 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1959 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1961 layertexrgbscale = 4;
1962 VectorScale(layer->color, 0.25f, layercolor);
1964 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
1966 layertexrgbscale = 2;
1967 VectorScale(layer->color, 0.5f, layercolor);
1971 layertexrgbscale = 1;
1972 VectorScale(layer->color, 1.0f, layercolor);
1974 layercolor[3] = layer->color[3];
1975 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1976 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
1977 switch (layer->type)
1979 case TEXTURELAYERTYPE_SKY:
1982 skyrendernow = false;
1983 if (skyrendermasked)
1986 // restore entity matrix and GL_Color
1987 R_Mesh_Matrix(&ent->matrix);
1988 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1991 // LordHavoc: HalfLife maps have freaky skypolys...
1992 //if (!ent->model->brush.ishlbsp)
1994 if (skyrendermasked)
1996 // depth-only (masking)
1997 GL_ColorMask(0,0,0,0);
1998 // just to make sure that braindead drivers don't draw anything
1999 // despite that colormask...
2000 GL_BlendFunc(GL_ZERO, GL_ONE);
2005 GL_BlendFunc(GL_ONE, GL_ZERO);
2007 memset(&m, 0, sizeof(m));
2009 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2011 surface = texturesurfacelist[texturesurfaceindex];
2012 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2013 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2014 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2015 GL_LockArrays(0, 0);
2017 if (skyrendermasked)
2018 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2021 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2022 memset(&m, 0, sizeof(m));
2023 m.tex[1] = R_GetTexture(layer->texture);
2024 m.texmatrix[1] = layer->texmatrix;
2025 m.texrgbscale[1] = layertexrgbscale;
2026 m.pointer_color = varray_color4f;
2028 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2030 surface = texturesurfacelist[texturesurfaceindex];
2031 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2032 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2033 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2036 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2037 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2039 else if (surface->lightmaptexture)
2041 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2042 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2046 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2047 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2049 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2050 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2051 GL_LockArrays(0, 0);
2054 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2055 memset(&m, 0, sizeof(m));
2056 m.tex[0] = R_GetTexture(layer->texture);
2057 m.texmatrix[0] = layer->texmatrix;
2058 m.pointer_color = varray_color4f;
2059 m.texrgbscale[0] = layertexrgbscale;
2061 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2063 surface = texturesurfacelist[texturesurfaceindex];
2064 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2065 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2068 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2069 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2071 else if (surface->lightmaptexture)
2073 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2074 R_Mesh_ColorPointer(NULL);
2078 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2079 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2081 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2082 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2083 GL_LockArrays(0, 0);
2085 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2086 memset(&m, 0, sizeof(m));
2087 m.tex[0] = R_GetTexture(layer->texture);
2088 m.texmatrix[0] = layer->texmatrix;
2089 m.pointer_color = varray_color4f;
2090 m.texrgbscale[0] = layertexrgbscale;
2092 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2094 surface = texturesurfacelist[texturesurfaceindex];
2095 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2096 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2097 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2098 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2099 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2100 GL_LockArrays(0, 0);
2103 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2104 memset(&m, 0, sizeof(m));
2105 m.tex[0] = R_GetTexture(layer->texture);
2106 m.texmatrix[0] = layer->texmatrix;
2107 m.texrgbscale[0] = layertexrgbscale;
2108 m.pointer_color = varray_color4f;
2110 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2112 surface = texturesurfacelist[texturesurfaceindex];
2113 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2114 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2115 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2116 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2117 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2118 GL_LockArrays(0, 0);
2121 case TEXTURELAYERTYPE_TEXTURE:
2122 memset(&m, 0, sizeof(m));
2123 m.tex[0] = R_GetTexture(layer->texture);
2124 m.texmatrix[0] = layer->texmatrix;
2125 m.pointer_color = varray_color4f;
2126 m.texrgbscale[0] = layertexrgbscale;
2128 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2130 surface = texturesurfacelist[texturesurfaceindex];
2131 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2132 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2133 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
2134 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2135 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2136 GL_LockArrays(0, 0);
2139 case TEXTURELAYERTYPE_FOG:
2140 memset(&m, 0, sizeof(m));
2143 m.tex[0] = R_GetTexture(layer->texture);
2144 m.texmatrix[0] = layer->texmatrix;
2147 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2151 surface = texturesurfacelist[texturesurfaceindex];
2152 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2154 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2155 R_Mesh_ColorPointer(varray_color4f);
2156 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)
2158 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2159 c[0] = layercolor[0];
2160 c[1] = layercolor[1];
2161 c[2] = layercolor[2];
2162 c[3] = f * layercolor[3];
2164 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2165 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2166 GL_LockArrays(0, 0);
2170 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2172 // if trying to do overbright on first pass of an opaque surface
2173 // when combine is not supported, brighten as a post process
2174 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2177 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2178 GL_Color(1, 1, 1, 1);
2179 memset(&m, 0, sizeof(m));
2181 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2183 surface = texturesurfacelist[texturesurfaceindex];
2184 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2185 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2186 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2187 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2188 GL_LockArrays(0, 0);
2192 if (r_shownormals.integer && !r_showtrispass)
2197 GL_DepthMask(texture->currentlayers->depthmask);
2198 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
2199 memset(&m, 0, sizeof(m));
2201 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2203 surface = texturesurfacelist[texturesurfaceindex];
2204 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2205 if (!rsurface_svector3f)
2207 rsurface_svector3f = varray_svector3f;
2208 rsurface_tvector3f = varray_tvector3f;
2209 rsurface_normal3f = varray_normal3f;
2210 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);
2212 GL_Color(1, 0, 0, 1);
2214 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2216 VectorCopy(rsurface_vertex3f + k * 3, v);
2217 qglVertex3f(v[0], v[1], v[2]);
2218 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
2219 qglVertex3f(v[0], v[1], v[2]);
2221 GL_Color(0, 0, 1, 1);
2222 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2224 VectorCopy(rsurface_vertex3f + k * 3, v);
2225 qglVertex3f(v[0], v[1], v[2]);
2226 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
2227 qglVertex3f(v[0], v[1], v[2]);
2229 GL_Color(0, 1, 0, 1);
2230 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2232 VectorCopy(rsurface_vertex3f + k * 3, v);
2233 qglVertex3f(v[0], v[1], v[2]);
2234 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
2235 qglVertex3f(v[0], v[1], v[2]);
2241 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2242 qglEnable(GL_CULL_FACE);
2245 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2247 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
2251 texture = surface->texture;
2252 if (texture->basematerialflags & MATERIALFLAG_SKY)
2253 return; // transparent sky is too difficult
2254 R_UpdateTextureInfo(ent, texture);
2256 R_Mesh_Matrix(&ent->matrix);
2257 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2258 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2261 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2263 int texturesurfaceindex;
2264 const msurface_t *surface;
2265 vec3_t tempcenter, center;
2266 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2268 // drawing sky transparently would be too difficult
2269 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2271 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2273 surface = texturesurfacelist[texturesurfaceindex];
2274 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2275 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2276 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2277 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2278 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
2283 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2286 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2287 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2289 int i, j, f, flagsmask;
2290 int counttriangles = 0;
2291 msurface_t *surface, **surfacechain;
2292 texture_t *t, *texture;
2293 model_t *model = ent->model;
2295 const int maxsurfacelist = 1024;
2296 int numsurfacelist = 0;
2297 const msurface_t *surfacelist[1024];
2300 R_Mesh_Matrix(&ent->matrix);
2301 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2303 // update light styles
2304 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2306 for (i = 0;i < model->brushq1.light_styles;i++)
2308 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2310 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2311 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2312 for (;(surface = *surfacechain);surfacechain++)
2313 surface->cached_dlight = true;
2318 R_UpdateAllTextureInfo(ent);
2319 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2324 if (ent == r_refdef.worldentity)
2326 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2328 if (!r_worldsurfacevisible[j])
2330 if (t != surface->texture)
2334 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2337 t = surface->texture;
2338 texture = t->currentframe;
2339 f = texture->currentmaterialflags & flagsmask;
2341 if (f && surface->num_triangles)
2343 // if lightmap parameters changed, rebuild lightmap texture
2344 if (surface->cached_dlight && surface->lightmapinfo->samples)
2345 R_BuildLightMap(ent, surface);
2346 // add face to draw list
2347 surfacelist[numsurfacelist++] = surface;
2348 counttriangles += surface->num_triangles;
2349 if (numsurfacelist >= maxsurfacelist)
2351 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2359 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2361 if (t != surface->texture)
2365 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2368 t = surface->texture;
2369 texture = t->currentframe;
2370 f = texture->currentmaterialflags & flagsmask;
2372 if (f && surface->num_triangles)
2374 // if lightmap parameters changed, rebuild lightmap texture
2375 if (surface->cached_dlight && surface->lightmapinfo->samples)
2376 R_BuildLightMap(ent, surface);
2377 // add face to draw list
2378 surfacelist[numsurfacelist++] = surface;
2379 counttriangles += surface->num_triangles;
2380 if (numsurfacelist >= maxsurfacelist)
2382 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2389 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2390 if (!r_showtrispass)
2391 renderstats.entities_triangles += counttriangles;