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
67 matrix4x4_t r_view_matrix;
74 cvar_t r_showtris = {0, "r_showtris", "0"};
75 cvar_t r_drawentities = {0, "r_drawentities","1"};
76 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
77 cvar_t r_speeds = {0, "r_speeds","0"};
78 cvar_t r_fullbright = {0, "r_fullbright","0"};
79 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
80 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
81 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
82 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
84 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
85 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
86 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
87 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
88 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
89 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
90 cvar_t gl_fogend = {0, "gl_fogend","0"};
92 cvar_t r_textureunits = {0, "r_textureunits", "32"};
94 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
95 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
96 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
98 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0"};
99 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "2"};
100 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "8"};
101 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
102 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"};
104 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1"};
106 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0"};
108 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
110 cvar_t r_test = {0, "r_test", "0"}; // used for testing renderer code changes, otherwise does nothing
112 rtexturepool_t *r_main_texturepool;
113 rtexture_t *r_bloom_texture_screen;
114 rtexture_t *r_bloom_texture_bloom;
115 rtexture_t *r_texture_blanknormalmap;
116 rtexture_t *r_texture_white;
117 rtexture_t *r_texture_black;
118 rtexture_t *r_texture_notexture;
119 rtexture_t *r_texture_whitecube;
120 rtexture_t *r_texture_normalizationcube;
121 rtexture_t *r_texture_fogattenuation;
122 rtexture_t *r_texture_fogintensity;
124 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
127 for (i = 0;i < verts;i++)
138 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
141 for (i = 0;i < verts;i++)
155 float fog_density, fog_red, fog_green, fog_blue;
157 qboolean oldgl_fogenable;
158 void R_UpdateFog(void)
160 if (gamemode == GAME_NEHAHRA)
162 if (gl_fogenable.integer)
164 oldgl_fogenable = true;
165 fog_density = gl_fogdensity.value;
166 fog_red = gl_fogred.value;
167 fog_green = gl_foggreen.value;
168 fog_blue = gl_fogblue.value;
170 else if (oldgl_fogenable)
172 oldgl_fogenable = false;
181 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
182 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
183 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
188 fogdensity = -4000.0f / (fog_density * fog_density);
189 // this is the point where the fog reaches 0.991373 alpha, which we
190 // consider a good enough cutoff point for the texture
191 fogrange = 400 / fog_density;
192 fograngerecip = 1.0f / fogrange;
193 // fog color was already set
199 // FIXME: move this to client?
202 if (gamemode == GAME_NEHAHRA)
204 Cvar_Set("gl_fogenable", "0");
205 Cvar_Set("gl_fogdensity", "0.2");
206 Cvar_Set("gl_fogred", "0.3");
207 Cvar_Set("gl_foggreen", "0.3");
208 Cvar_Set("gl_fogblue", "0.3");
210 fog_density = fog_red = fog_green = fog_blue = 0.0f;
213 // FIXME: move this to client?
214 void FOG_registercvars(void)
216 if (gamemode == GAME_NEHAHRA)
218 Cvar_RegisterVariable (&gl_fogenable);
219 Cvar_RegisterVariable (&gl_fogdensity);
220 Cvar_RegisterVariable (&gl_fogred);
221 Cvar_RegisterVariable (&gl_foggreen);
222 Cvar_RegisterVariable (&gl_fogblue);
223 Cvar_RegisterVariable (&gl_fogstart);
224 Cvar_RegisterVariable (&gl_fogend);
228 static void R_BuildBlankTextures(void)
231 data[0] = 128; // normal X
232 data[1] = 128; // normal Y
233 data[2] = 255; // normal Z
234 data[3] = 128; // height
235 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
240 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
245 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
248 static void R_BuildNoTexture(void)
251 qbyte pix[16][16][4];
252 // this makes a light grey/dark grey checkerboard texture
253 for (y = 0;y < 16;y++)
255 for (x = 0;x < 16;x++)
257 if ((y < 8) ^ (x < 8))
273 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
276 static void R_BuildWhiteCube(void)
279 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
280 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
281 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
282 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
283 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
284 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
285 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
288 static void R_BuildNormalizationCube(void)
292 vec_t s, t, intensity;
294 qbyte data[6][NORMSIZE][NORMSIZE][4];
295 for (side = 0;side < 6;side++)
297 for (y = 0;y < NORMSIZE;y++)
299 for (x = 0;x < NORMSIZE;x++)
301 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
302 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
337 intensity = 127.0f / sqrt(DotProduct(v, v));
338 data[side][y][x][0] = 128.0f + intensity * v[0];
339 data[side][y][x][1] = 128.0f + intensity * v[1];
340 data[side][y][x][2] = 128.0f + intensity * v[2];
341 data[side][y][x][3] = 255;
345 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
348 static void R_BuildFogTexture(void)
353 qbyte data1[FOGWIDTH][4];
354 qbyte data2[FOGWIDTH][4];
355 r = (-65536.0 / (FOGWIDTH*FOGWIDTH));
356 for (x = 0;x < FOGWIDTH;x++)
358 b = (int)(256.0 * exp(r / ((double)x*(double)x)));
359 b = bound(0, b, 255);
360 data1[x][0] = 255 - b;
361 data1[x][1] = 255 - b;
362 data1[x][2] = 255 - b;
369 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
370 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
373 void gl_main_start(void)
375 r_main_texturepool = R_AllocTexturePool();
376 r_bloom_texture_screen = NULL;
377 r_bloom_texture_bloom = NULL;
378 R_BuildBlankTextures();
380 if (gl_texturecubemap)
383 R_BuildNormalizationCube();
388 void gl_main_shutdown(void)
390 R_FreeTexturePool(&r_main_texturepool);
391 r_bloom_texture_screen = NULL;
392 r_bloom_texture_bloom = NULL;
393 r_texture_blanknormalmap = NULL;
394 r_texture_white = NULL;
395 r_texture_black = NULL;
396 r_texture_whitecube = NULL;
397 r_texture_normalizationcube = NULL;
400 extern void CL_ParseEntityLump(char *entitystring);
401 void gl_main_newmap(void)
403 // FIXME: move this code to client
405 char *entities, entname[MAX_QPATH];
409 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
410 l = (int)strlen(entname) - 4;
411 if (l >= 0 && !strcmp(entname + l, ".bsp"))
413 strcpy(entname + l, ".ent");
414 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true)))
416 CL_ParseEntityLump(entities);
421 if (cl.worldmodel->brush.entities)
422 CL_ParseEntityLump(cl.worldmodel->brush.entities);
426 void GL_Main_Init(void)
428 Matrix4x4_CreateIdentity(&r_identitymatrix);
429 // FIXME: move this to client?
431 Cvar_RegisterVariable(&r_showtris);
432 Cvar_RegisterVariable(&r_drawentities);
433 Cvar_RegisterVariable(&r_drawviewmodel);
434 Cvar_RegisterVariable(&r_speeds);
435 Cvar_RegisterVariable(&r_fullbrights);
436 Cvar_RegisterVariable(&r_wateralpha);
437 Cvar_RegisterVariable(&r_dynamic);
438 Cvar_RegisterVariable(&r_fullbright);
439 Cvar_RegisterVariable(&r_textureunits);
440 Cvar_RegisterVariable(&r_lerpsprites);
441 Cvar_RegisterVariable(&r_lerpmodels);
442 Cvar_RegisterVariable(&r_waterscroll);
443 Cvar_RegisterVariable(&r_drawcollisionbrushes);
444 Cvar_RegisterVariable(&r_bloom);
445 Cvar_RegisterVariable(&r_bloom_intensity);
446 Cvar_RegisterVariable(&r_bloom_blur);
447 Cvar_RegisterVariable(&r_bloom_resolution);
448 Cvar_RegisterVariable(&r_bloom_power);
449 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
450 Cvar_RegisterVariable(&developer_texturelogging);
451 Cvar_RegisterVariable(&gl_lightmaps);
452 Cvar_RegisterVariable(&r_test);
453 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
454 Cvar_SetValue("r_fullbrights", 0);
455 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
458 static vec3_t r_farclip_origin;
459 static vec3_t r_farclip_direction;
460 static vec_t r_farclip_directiondist;
461 static vec_t r_farclip_meshfarclip;
462 static int r_farclip_directionbit0;
463 static int r_farclip_directionbit1;
464 static int r_farclip_directionbit2;
466 // enlarge farclip to accomodate box
467 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
470 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
471 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
472 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
473 if (r_farclip_meshfarclip < d)
474 r_farclip_meshfarclip = d;
477 // return farclip value
478 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
482 VectorCopy(origin, r_farclip_origin);
483 VectorCopy(direction, r_farclip_direction);
484 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
485 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
486 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
487 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
488 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
490 if (r_refdef.worldmodel)
491 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
492 for (i = 0;i < r_refdef.numentities;i++)
493 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
495 return r_farclip_meshfarclip - r_farclip_directiondist;
498 extern void R_Textures_Init(void);
499 extern void GL_Draw_Init(void);
500 extern void GL_Main_Init(void);
501 extern void R_Shadow_Init(void);
502 extern void R_Sky_Init(void);
503 extern void GL_Surf_Init(void);
504 extern void R_Crosshairs_Init(void);
505 extern void R_Light_Init(void);
506 extern void R_Particles_Init(void);
507 extern void R_Explosion_Init(void);
508 extern void gl_backend_init(void);
509 extern void Sbar_Init(void);
510 extern void R_LightningBeams_Init(void);
511 extern void Mod_RenderInit(void);
513 void Render_Init(void)
529 R_LightningBeams_Init();
538 extern char *ENGINE_EXTENSIONS;
541 VID_CheckExtensions();
543 // LordHavoc: report supported extensions
544 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
546 // clear to black (loading plaque will be seen over this)
547 qglClearColor(0,0,0,1);
548 qglClear(GL_COLOR_BUFFER_BIT);
551 int R_CullBox(const vec3_t mins, const vec3_t maxs)
555 for (i = 0;i < 4;i++)
562 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
566 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
570 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
574 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
578 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
582 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
586 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
590 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
598 //==================================================================================
600 static void R_MarkEntities (void)
603 entity_render_t *ent;
605 if (!r_drawentities.integer)
608 r_refdef.worldentity->visframe = r_framecount;
609 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
610 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
612 // worldmodel can check visibility
613 for (i = 0;i < r_refdef.numentities;i++)
615 ent = r_refdef.entities[i];
616 // some of the renderer still relies on origin...
617 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
618 // some of the renderer still relies on scale...
619 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
620 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)))
622 R_UpdateEntLights(ent);
623 ent->visframe = r_framecount;
629 // no worldmodel or it can't check visibility
630 for (i = 0;i < r_refdef.numentities;i++)
632 ent = r_refdef.entities[i];
633 // some of the renderer still relies on origin...
634 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
635 // some of the renderer still relies on scale...
636 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
637 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
639 R_UpdateEntLights(ent);
640 ent->visframe = r_framecount;
646 // only used if skyrendermasked, and normally returns false
647 int R_DrawBrushModelsSky (void)
650 entity_render_t *ent;
652 if (!r_drawentities.integer)
656 for (i = 0;i < r_refdef.numentities;i++)
658 ent = r_refdef.entities[i];
659 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
661 ent->model->DrawSky(ent);
668 void R_DrawNoModel(entity_render_t *ent);
669 void R_DrawModels(void)
672 entity_render_t *ent;
674 if (!r_drawentities.integer)
677 for (i = 0;i < r_refdef.numentities;i++)
679 ent = r_refdef.entities[i];
680 if (ent->visframe == r_framecount)
682 renderstats.entities++;
683 if (ent->model && ent->model->Draw != NULL)
684 ent->model->Draw(ent);
691 static void R_SetFrustum(void)
693 // break apart the view matrix into vectors for various purposes
694 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
695 VectorNegate(r_viewleft, r_viewright);
697 // LordHavoc: note to all quake engine coders, the special case for 90
698 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
701 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
702 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
703 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
704 PlaneClassify(&frustum[0]);
706 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
707 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
708 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
709 PlaneClassify(&frustum[1]);
711 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
712 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
713 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
714 PlaneClassify(&frustum[2]);
716 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
717 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
718 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
719 PlaneClassify(&frustum[3]);
722 VectorCopy(r_viewforward, frustum[4].normal);
723 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
724 PlaneClassify(&frustum[4]);
727 static void R_BlendView(void)
731 if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
734 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
737 R_Mesh_Matrix(&r_identitymatrix);
738 // vertex coordinates for a quad that covers the screen exactly
739 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
740 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
741 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
742 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
743 if (r_bloom.integer && 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)
745 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
746 float xoffset, yoffset, r;
748 // set the (poorly named) screenwidth and screenheight variables to
749 // a power of 2 at least as large as the screen, these will define the
750 // size of the texture to allocate
751 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
752 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
753 // allocate textures as needed
754 if (!r_bloom_texture_screen)
755 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
756 if (!r_bloom_texture_bloom)
757 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
758 // set bloomwidth and bloomheight to the bloom resolution that will be
759 // used (often less than the screen resolution for faster rendering)
760 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
761 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
762 // set up a texcoord array for the full resolution screen image
763 // (we have to keep this around to copy back during final render)
764 varray_texcoord2f[0][0] = 0;
765 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
766 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
767 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
768 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
769 varray_texcoord2f[0][5] = 0;
770 varray_texcoord2f[0][6] = 0;
771 varray_texcoord2f[0][7] = 0;
772 // set up a texcoord array for the reduced resolution bloom image
773 // (which will be additive blended over the screen image)
774 varray_texcoord2f[1][0] = 0;
775 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
776 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
777 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
778 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
779 varray_texcoord2f[1][5] = 0;
780 varray_texcoord2f[1][6] = 0;
781 varray_texcoord2f[1][7] = 0;
782 memset(&m, 0, sizeof(m));
783 m.pointer_vertex = varray_vertex3f;
784 m.pointer_texcoord[0] = varray_texcoord2f[0];
785 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
787 // copy view into the full resolution screen image texture
789 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
790 renderstats.bloom_copypixels += r_view_width * r_view_height;
791 // now scale it down to the bloom size and raise to a power of itself
792 // to darken it (this leaves the really bright stuff bright, and
793 // everything else becomes very dark)
794 // TODO: optimize with multitexture or GLSL
795 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
796 GL_BlendFunc(GL_ONE, GL_ZERO);
797 GL_Color(1, 1, 1, 1);
798 R_Mesh_Draw(0, 4, 2, polygonelements);
799 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
800 // render multiple times with a multiply blendfunc to raise to a power
801 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
802 for (x = 1;x < r_bloom_power.integer;x++)
804 R_Mesh_Draw(0, 4, 2, polygonelements);
805 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
807 // we now have a darkened bloom image in the framebuffer, copy it into
808 // the bloom image texture for more processing
809 memset(&m, 0, sizeof(m));
810 m.pointer_vertex = varray_vertex3f;
811 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
812 m.pointer_texcoord[0] = varray_texcoord2f[2];
815 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
816 renderstats.bloom_copypixels += bloomwidth * bloomheight;
817 // blend on at multiple vertical offsets to achieve a vertical blur
818 // TODO: do offset blends using GLSL
819 range = r_bloom_blur.integer * bloomwidth / 320;
820 GL_BlendFunc(GL_ONE, GL_ZERO);
821 for (x = -range;x <= range;x++)
823 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
824 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
825 // compute a texcoord array with the specified x and y offset
826 varray_texcoord2f[2][0] = xoffset+0;
827 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
828 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
829 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
830 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
831 varray_texcoord2f[2][5] = yoffset+0;
832 varray_texcoord2f[2][6] = xoffset+0;
833 varray_texcoord2f[2][7] = yoffset+0;
834 // this r value looks like a 'dot' particle, fading sharply to
835 // black at the edges
836 // (probably not realistic but looks good enough)
837 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
840 GL_Color(r, r, r, 1);
841 R_Mesh_Draw(0, 4, 2, polygonelements);
842 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
843 GL_BlendFunc(GL_ONE, GL_ONE);
845 // copy the vertically blurred bloom view to a texture
847 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
848 renderstats.bloom_copypixels += bloomwidth * bloomheight;
849 // blend the vertically blurred image at multiple offsets horizontally
850 // to finish the blur effect
851 // TODO: do offset blends using GLSL
852 range = r_bloom_blur.integer * bloomwidth / 320;
853 GL_BlendFunc(GL_ONE, GL_ZERO);
854 for (x = -range;x <= range;x++)
856 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
857 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
858 // compute a texcoord array with the specified x and y offset
859 varray_texcoord2f[2][0] = xoffset+0;
860 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
861 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
862 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
863 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
864 varray_texcoord2f[2][5] = yoffset+0;
865 varray_texcoord2f[2][6] = xoffset+0;
866 varray_texcoord2f[2][7] = yoffset+0;
867 // this r value looks like a 'dot' particle, fading sharply to
868 // black at the edges
869 // (probably not realistic but looks good enough)
870 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
873 GL_Color(r, r, r, 1);
874 R_Mesh_Draw(0, 4, 2, polygonelements);
875 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
876 GL_BlendFunc(GL_ONE, GL_ONE);
878 // copy the blurred bloom view to a texture
880 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
881 renderstats.bloom_copypixels += bloomwidth * bloomheight;
882 // go back to full view area
883 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
884 // put the original screen image back in place and blend the bloom
886 memset(&m, 0, sizeof(m));
887 m.pointer_vertex = varray_vertex3f;
888 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
889 m.pointer_texcoord[0] = varray_texcoord2f[0];
891 dobloomblend = false;
893 // do both in one pass if possible
894 if (r_textureunits.integer >= 2 && gl_combine.integer)
896 dobloomblend = false;
897 m.texcombinergb[1] = GL_ADD;
898 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
899 m.pointer_texcoord[1] = varray_texcoord2f[1];
905 GL_BlendFunc(GL_ONE, GL_ZERO);
907 R_Mesh_Draw(0, 4, 2, polygonelements);
908 renderstats.bloom_drawpixels += r_view_width * r_view_height;
909 // now blend on the bloom texture if multipass
912 memset(&m, 0, sizeof(m));
913 m.pointer_vertex = varray_vertex3f;
914 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
915 m.pointer_texcoord[0] = varray_texcoord2f[1];
917 GL_BlendFunc(GL_ONE, GL_ONE);
919 R_Mesh_Draw(0, 4, 2, polygonelements);
920 renderstats.bloom_drawpixels += r_view_width * r_view_height;
923 if (r_refdef.viewblend[3] >= 0.01f)
925 // apply a color tint to the whole view
926 memset(&m, 0, sizeof(m));
927 m.pointer_vertex = varray_vertex3f;
929 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
930 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
931 R_Mesh_Draw(0, 4, 2, polygonelements);
935 void R_RenderScene(void);
937 matrix4x4_t r_waterscrollmatrix;
944 void R_RenderView(void)
946 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
947 return; //Host_Error ("R_RenderView: NULL worldmodel");
949 r_view_width = bound(0, r_refdef.width, vid.width);
950 r_view_height = bound(0, r_refdef.height, vid.height);
952 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
953 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
955 r_view_fov_x = bound(1, r_refdef.fov_x, 170);
956 r_view_fov_y = bound(1, r_refdef.fov_y, 170);
957 r_view_matrix = r_refdef.viewentitymatrix;
958 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
959 r_rtworld = r_shadow_realtime_world.integer;
960 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
961 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
962 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
963 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
965 // GL is weird because it's bottom to top, r_view_y is top to bottom
966 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
967 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
968 GL_ScissorTest(true);
973 R_TimeReport("setup");
975 qglDepthFunc(GL_LEQUAL);
976 qglPolygonOffset(0, 0);
977 qglEnable(GL_POLYGON_OFFSET_FILL);
981 qglPolygonOffset(0, 0);
982 qglDisable(GL_POLYGON_OFFSET_FILL);
985 R_TimeReport("blendview");
987 GL_Scissor(0, 0, vid.width, vid.height);
988 GL_ScissorTest(false);
991 extern void R_DrawLightningBeams (void);
992 void R_RenderScene(void)
994 // don't let sound skip if going slow
995 if (r_refdef.extraupdate)
1000 R_MeshQueue_BeginScene();
1002 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1006 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1007 if (r_rtworldshadows || r_rtdlightshadows)
1008 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
1010 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
1012 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1014 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);
1018 R_WorldVisibility();
1019 R_TimeReport("worldvis");
1022 R_TimeReport("markentity");
1024 R_Shadow_UpdateWorldLightSelection();
1026 // don't let sound skip if going slow
1027 if (r_refdef.extraupdate)
1030 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1031 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1033 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1034 R_TimeReport("worldsky");
1037 if (R_DrawBrushModelsSky())
1038 R_TimeReport("bmodelsky");
1040 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1041 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1043 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1044 R_TimeReport("world");
1047 // don't let sound skip if going slow
1048 if (r_refdef.extraupdate)
1051 GL_ShowTrisColor(0, 0.015, 0, 1);
1054 R_TimeReport("models");
1056 // don't let sound skip if going slow
1057 if (r_refdef.extraupdate)
1060 GL_ShowTrisColor(0, 0, 0.033, 1);
1061 R_ShadowVolumeLighting(false);
1062 R_TimeReport("rtlights");
1064 // don't let sound skip if going slow
1065 if (r_refdef.extraupdate)
1068 GL_ShowTrisColor(0.1, 0, 0, 1);
1070 R_DrawLightningBeams();
1071 R_TimeReport("lightning");
1074 R_TimeReport("particles");
1077 R_TimeReport("explosions");
1079 R_MeshQueue_RenderTransparent();
1080 R_TimeReport("drawtrans");
1083 R_TimeReport("coronas");
1085 R_DrawWorldCrosshair();
1086 R_TimeReport("crosshair");
1088 R_MeshQueue_Render();
1089 R_MeshQueue_EndScene();
1091 if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1093 R_ShadowVolumeLighting(true);
1094 R_TimeReport("visiblevolume");
1097 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1099 // don't let sound skip if going slow
1100 if (r_refdef.extraupdate)
1105 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1108 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1110 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1111 GL_DepthMask(false);
1113 R_Mesh_Matrix(&r_identitymatrix);
1115 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1116 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1117 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1118 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1119 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1120 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1121 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1122 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1123 R_FillColors(color, 8, cr, cg, cb, ca);
1126 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1128 VectorSubtract(v, r_vieworigin, diff);
1129 f2 = exp(fogdensity/DotProduct(diff, diff));
1131 c[0] = c[0] * f1 + fogcolor[0] * f2;
1132 c[1] = c[1] * f1 + fogcolor[1] * f2;
1133 c[2] = c[2] * f1 + fogcolor[2] * f2;
1136 memset(&m, 0, sizeof(m));
1137 m.pointer_vertex = vertex3f;
1138 m.pointer_color = color;
1144 int nomodelelements[24] =
1156 float nomodelvertex3f[6*3] =
1166 float nomodelcolor4f[6*4] =
1168 0.0f, 0.0f, 0.5f, 1.0f,
1169 0.0f, 0.0f, 0.5f, 1.0f,
1170 0.0f, 0.5f, 0.0f, 1.0f,
1171 0.0f, 0.5f, 0.0f, 1.0f,
1172 0.5f, 0.0f, 0.0f, 1.0f,
1173 0.5f, 0.0f, 0.0f, 1.0f
1176 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1178 const entity_render_t *ent = (entity_render_t *)calldata1;
1180 float f1, f2, *c, diff[3];
1183 R_Mesh_Matrix(&ent->matrix);
1185 memset(&m, 0, sizeof(m));
1186 m.pointer_vertex = nomodelvertex3f;
1188 if (ent->flags & EF_ADDITIVE)
1190 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1191 GL_DepthMask(false);
1193 else if (ent->alpha < 1)
1195 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1196 GL_DepthMask(false);
1200 GL_BlendFunc(GL_ONE, GL_ZERO);
1203 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1206 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1207 m.pointer_color = color4f;
1208 VectorSubtract(ent->origin, r_vieworigin, diff);
1209 f2 = exp(fogdensity/DotProduct(diff, diff));
1211 for (i = 0, c = color4f;i < 6;i++, c += 4)
1213 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1214 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1215 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1219 else if (ent->alpha != 1)
1221 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1222 m.pointer_color = color4f;
1223 for (i = 0, c = color4f;i < 6;i++, c += 4)
1227 m.pointer_color = nomodelcolor4f;
1229 R_Mesh_Draw(0, 6, 8, nomodelelements);
1232 void R_DrawNoModel(entity_render_t *ent)
1234 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1235 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1237 // R_DrawNoModelCallback(ent, 0);
1240 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1242 vec3_t right1, right2, diff, normal;
1244 VectorSubtract (org2, org1, normal);
1246 // calculate 'right' vector for start
1247 VectorSubtract (r_vieworigin, org1, diff);
1248 CrossProduct (normal, diff, right1);
1249 VectorNormalize (right1);
1251 // calculate 'right' vector for end
1252 VectorSubtract (r_vieworigin, org2, diff);
1253 CrossProduct (normal, diff, right2);
1254 VectorNormalize (right2);
1256 vert[ 0] = org1[0] + width * right1[0];
1257 vert[ 1] = org1[1] + width * right1[1];
1258 vert[ 2] = org1[2] + width * right1[2];
1259 vert[ 3] = org1[0] - width * right1[0];
1260 vert[ 4] = org1[1] - width * right1[1];
1261 vert[ 5] = org1[2] - width * right1[2];
1262 vert[ 6] = org2[0] - width * right2[0];
1263 vert[ 7] = org2[1] - width * right2[1];
1264 vert[ 8] = org2[2] - width * right2[2];
1265 vert[ 9] = org2[0] + width * right2[0];
1266 vert[10] = org2[1] + width * right2[1];
1267 vert[11] = org2[2] + width * right2[2];
1270 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1272 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, 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)
1279 VectorSubtract(origin, r_vieworigin, diff);
1280 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1283 R_Mesh_Matrix(&r_identitymatrix);
1284 GL_BlendFunc(blendfunc1, blendfunc2);
1285 GL_DepthMask(false);
1286 GL_DepthTest(!depthdisable);
1288 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1289 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1290 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1291 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1292 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1293 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1294 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1295 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1296 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1297 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1298 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1299 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1301 memset(&m, 0, sizeof(m));
1302 m.tex[0] = R_GetTexture(texture);
1303 m.pointer_texcoord[0] = spritetexcoord2f;
1304 m.pointer_vertex = varray_vertex3f;
1306 GL_Color(cr, cg, cb, ca);
1307 R_Mesh_Draw(0, 4, 2, polygonelements);
1310 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1314 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1315 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1317 if (i == mesh->numvertices)
1319 if (mesh->numvertices < mesh->maxvertices)
1321 VectorCopy(v, vertex3f);
1322 mesh->numvertices++;
1324 return mesh->numvertices;
1330 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1334 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1335 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1336 e = mesh->element3i + mesh->numtriangles * 3;
1337 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1339 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1340 if (mesh->numtriangles < mesh->maxtriangles)
1345 mesh->numtriangles++;
1347 element[1] = element[2];
1351 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1353 int planenum, planenum2;
1356 mplane_t *plane, *plane2;
1357 float temppoints[2][256*3];
1358 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1362 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1363 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1365 if (planenum2 == planenum)
1367 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);
1370 if (tempnumpoints < 3)
1372 // generate elements forming a triangle fan for this polygon
1373 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1377 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)
1379 texturelayer_t *layer;
1380 layer = t->currentlayers + t->currentnumlayers++;
1382 layer->depthmask = depthmask;
1383 layer->blendfunc1 = blendfunc1;
1384 layer->blendfunc2 = blendfunc2;
1385 layer->texture = texture;
1386 layer->texmatrix = *matrix;
1387 layer->color[0] = r;
1388 layer->color[1] = g;
1389 layer->color[2] = b;
1390 layer->color[3] = a;
1393 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1395 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1396 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1400 texture_t *texture = t;
1401 model_t *model = ent->model;
1402 int s = ent->skinnum;
1403 if ((unsigned int)s >= (unsigned int)model->numskins)
1405 if (model->skinscenes)
1407 if (model->skinscenes[s].framecount > 1)
1408 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1410 s = model->skinscenes[s].firstframe;
1413 t = t + s * model->num_surfaces;
1415 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];
1416 texture->currentframe = t;
1419 t->currentmaterialflags = t->basematerialflags;
1420 currentalpha = ent->alpha;
1421 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1422 currentalpha *= r_wateralpha.value;
1423 if (!(ent->flags & RENDER_LIGHT))
1424 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1425 if (ent->effects & EF_ADDITIVE)
1426 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1427 else if (currentalpha < 1)
1428 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1429 if (ent->effects & EF_NODEPTHTEST)
1430 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1431 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1432 t->currenttexmatrix = r_waterscrollmatrix;
1434 t->currenttexmatrix = r_identitymatrix;
1435 t->currentnumlayers = 0;
1436 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1438 if (gl_lightmaps.integer)
1439 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1440 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1442 // transparent sky would be ridiculous
1443 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1444 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1448 int blendfunc1, blendfunc2, depthmask;
1449 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1451 blendfunc1 = GL_SRC_ALPHA;
1452 blendfunc2 = GL_ONE;
1455 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1457 blendfunc1 = GL_SRC_ALPHA;
1458 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1463 blendfunc1 = GL_ONE;
1464 blendfunc2 = GL_ZERO;
1467 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1469 rtexture_t *currentbasetexture;
1471 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1472 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1473 currentbasetexture = (ent->colormap < 0 && t->skin.merged) ? t->skin.merged : t->skin.base;
1474 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1476 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], currentalpha);
1477 if (ent->colormap >= 0 && t->skin.pants)
1478 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2], currentalpha);
1479 if (ent->colormap >= 0 && t->skin.shirt)
1480 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2], currentalpha);
1486 // q3bsp has no lightmap updates, so the lightstylevalue that
1487 // would normally be baked into the lightmaptexture must be
1488 // applied to the color
1489 if (ent->model->type == mod_brushq3)
1490 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1491 // transparent and fullbright are not affected by r_lightmapintensity
1492 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1493 colorscale *= r_lightmapintensity;
1494 if (r_textureunits.integer >= 2 && gl_combine.integer)
1495 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, currentalpha);
1496 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1497 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, currentalpha);
1499 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, currentalpha);
1500 if (r_ambient.value >= (1.0f/64.0f))
1501 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), currentalpha);
1502 if (ent->colormap >= 0 && t->skin.pants)
1504 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * colorscale, ent->colormap_pantscolor[1] * colorscale, ent->colormap_pantscolor[2] * colorscale, currentalpha);
1505 if (r_ambient.value >= (1.0f/64.0f))
1506 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * r_ambient.value * (1.0f / 64.0f), currentalpha);
1508 if (ent->colormap >= 0 && t->skin.shirt)
1510 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * colorscale, ent->colormap_shirtcolor[1] * colorscale, ent->colormap_shirtcolor[2] * colorscale, currentalpha);
1511 if (r_ambient.value >= (1.0f/64.0f))
1512 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * r_ambient.value * (1.0f / 64.0f), currentalpha);
1515 if (t->skin.glow != NULL)
1516 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, currentalpha);
1517 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1519 // if this is opaque use alpha blend which will darken the earlier
1522 // if this is an alpha blended material, all the earlier passes
1523 // were darkened by fog already, so we only need to add the fog
1524 // color ontop through the fog mask texture
1526 // if this is an additive blended material, all the earlier passes
1527 // were darkened by fog already, and we should not add fog color
1528 // (because the background was not darkened, there is no fog color
1529 // that was lost behind it).
1530 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], currentalpha);
1537 void R_UpdateAllTextureInfo(entity_render_t *ent)
1541 for (i = 0;i < ent->model->num_textures;i++)
1542 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1545 float *rsurface_vertex3f;
1546 float *rsurface_svector3f;
1547 float *rsurface_tvector3f;
1548 float *rsurface_normal3f;
1549 float *rsurface_lightmapcolor4f;
1551 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1554 float center[3], forward[3], right[3], up[3], v[4][3];
1555 matrix4x4_t matrix1, imatrix1;
1556 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1558 rsurface_vertex3f = varray_vertex3f;
1559 rsurface_svector3f = NULL;
1560 rsurface_tvector3f = NULL;
1561 rsurface_normal3f = NULL;
1562 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1566 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1567 rsurface_svector3f = surface->groupmesh->data_svector3f;
1568 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1569 rsurface_normal3f = surface->groupmesh->data_normal3f;
1571 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1573 if (!rsurface_svector3f)
1575 rsurface_svector3f = varray_svector3f;
1576 rsurface_tvector3f = varray_tvector3f;
1577 rsurface_normal3f = varray_normal3f;
1578 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);
1580 // a single autosprite surface can contain multiple sprites...
1581 VectorClear(forward);
1583 VectorSet(up, 0, 0, 1);
1584 for (j = 0;j < surface->num_vertices - 3;j += 4)
1586 VectorClear(center);
1587 for (i = 0;i < 4;i++)
1588 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1589 VectorScale(center, 0.25f, center);
1590 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1591 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);
1592 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1593 for (i = 0;i < 4;i++)
1594 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1595 forward[0] = modelorg[0] - center[0];
1596 forward[1] = modelorg[1] - center[1];
1597 VectorNormalize(forward);
1598 right[0] = forward[1];
1599 right[1] = -forward[0];
1600 for (i = 0;i < 4;i++)
1601 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1603 rsurface_vertex3f = varray_vertex3f;
1604 rsurface_svector3f = NULL;
1605 rsurface_tvector3f = NULL;
1606 rsurface_normal3f = NULL;
1608 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1610 if (!rsurface_svector3f)
1612 rsurface_svector3f = varray_svector3f;
1613 rsurface_tvector3f = varray_tvector3f;
1614 rsurface_normal3f = varray_normal3f;
1615 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);
1617 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1618 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1619 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1620 // a single autosprite surface can contain multiple sprites...
1621 for (j = 0;j < surface->num_vertices - 3;j += 4)
1623 VectorClear(center);
1624 for (i = 0;i < 4;i++)
1625 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1626 VectorScale(center, 0.25f, center);
1627 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1628 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);
1629 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1630 for (i = 0;i < 4;i++)
1631 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1632 for (i = 0;i < 4;i++)
1633 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1635 rsurface_vertex3f = varray_vertex3f;
1636 rsurface_svector3f = NULL;
1637 rsurface_tvector3f = NULL;
1638 rsurface_normal3f = NULL;
1640 R_Mesh_VertexPointer(rsurface_vertex3f);
1643 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)
1652 vec4_t ambientcolor4f;
1653 vec3_t diffusecolor;
1654 vec3_t diffusenormal;
1655 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1657 rsurface_lightmapcolor4f = varray_color4f;
1658 if (rsurface_normal3f == NULL)
1660 rsurface_normal3f = varray_normal3f;
1661 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);
1663 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);
1672 r = ambientcolor4f[0];
1673 g = ambientcolor4f[1];
1674 b = ambientcolor4f[2];
1675 a = ambientcolor4f[3];
1676 rsurface_lightmapcolor4f = NULL;
1679 else if (lightmode >= 1)
1681 if (surface->lightmapinfo)
1683 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1685 const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1688 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1689 VectorScale(lm, scale, c);
1690 if (surface->lightmapinfo->styles[1] != 255)
1692 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1694 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1695 VectorMA(c, scale, lm, c);
1696 if (surface->lightmapinfo->styles[2] != 255)
1699 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1700 VectorMA(c, scale, lm, c);
1701 if (surface->lightmapinfo->styles[3] != 255)
1704 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1705 VectorMA(c, scale, lm, c);
1713 rsurface_lightmapcolor4f = varray_color4f;
1716 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1719 rsurface_lightmapcolor4f = NULL;
1722 if (rsurface_lightmapcolor4f)
1724 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)
1726 VectorSubtract(v, modelorg, diff);
1727 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1736 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)
1738 VectorSubtract(v, modelorg, diff);
1739 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1746 rsurface_lightmapcolor4f = varray_color4f;
1748 if (applycolor && rsurface_lightmapcolor4f)
1750 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)
1757 rsurface_lightmapcolor4f = varray_color4f;
1759 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1760 GL_Color(r, g, b, a);
1764 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1766 int texturesurfaceindex;
1768 const msurface_t *surface;
1769 qboolean applycolor;
1771 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1773 renderstats.entities_surfaces += texturenumsurfaces;
1774 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1775 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1776 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1777 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1778 qglDisable(GL_CULL_FACE);
1779 if (texture->currentnumlayers)
1782 texturelayer_t *layer;
1783 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1786 int layertexrgbscale;
1787 GL_DepthMask(layer->depthmask);
1788 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1789 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1791 layertexrgbscale = 4;
1792 VectorScale(layer->color, 0.25f, layercolor);
1794 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
1796 layertexrgbscale = 2;
1797 VectorScale(layer->color, 0.5f, layercolor);
1801 layertexrgbscale = 1;
1802 VectorScale(layer->color, 1.0f, layercolor);
1804 layercolor[3] = layer->color[3];
1805 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1806 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
1807 switch (layer->type)
1809 case TEXTURELAYERTYPE_SKY:
1812 skyrendernow = false;
1813 if (skyrendermasked)
1816 // restore entity matrix and GL_Color
1817 R_Mesh_Matrix(&ent->matrix);
1818 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1821 // LordHavoc: HalfLife maps have freaky skypolys...
1822 //if (!ent->model->brush.ishlbsp)
1824 if (skyrendermasked)
1826 // depth-only (masking)
1827 GL_ColorMask(0,0,0,0);
1828 // just to make sure that braindead drivers don't draw anything
1829 // despite that colormask...
1830 GL_BlendFunc(GL_ZERO, GL_ONE);
1835 GL_BlendFunc(GL_ONE, GL_ZERO);
1837 memset(&m, 0, sizeof(m));
1839 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1841 surface = texturesurfacelist[texturesurfaceindex];
1842 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1843 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1844 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1845 GL_LockArrays(0, 0);
1847 if (skyrendermasked)
1848 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1851 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
1852 memset(&m, 0, sizeof(m));
1853 m.tex[1] = R_GetTexture(layer->texture);
1854 m.texmatrix[1] = layer->texmatrix;
1855 m.texrgbscale[1] = layertexrgbscale;
1856 m.pointer_color = varray_color4f;
1858 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1860 surface = texturesurfacelist[texturesurfaceindex];
1861 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1862 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1863 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1866 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1867 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1869 else if (surface->lightmaptexture)
1871 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1872 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1876 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1877 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1879 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1880 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1881 GL_LockArrays(0, 0);
1884 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
1885 memset(&m, 0, sizeof(m));
1886 m.tex[0] = R_GetTexture(layer->texture);
1887 m.texmatrix[0] = layer->texmatrix;
1888 m.pointer_color = varray_color4f;
1889 m.texrgbscale[0] = layertexrgbscale;
1891 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1893 surface = texturesurfacelist[texturesurfaceindex];
1894 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1895 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1898 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1899 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
1901 else if (surface->lightmaptexture)
1903 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1904 R_Mesh_ColorPointer(NULL);
1908 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1909 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
1911 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1912 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1913 GL_LockArrays(0, 0);
1915 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1916 memset(&m, 0, sizeof(m));
1917 m.tex[0] = R_GetTexture(layer->texture);
1918 m.texmatrix[0] = layer->texmatrix;
1919 m.pointer_color = varray_color4f;
1920 m.texrgbscale[0] = layertexrgbscale;
1922 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1924 surface = texturesurfacelist[texturesurfaceindex];
1925 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1926 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1927 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1928 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1929 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1930 GL_LockArrays(0, 0);
1933 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
1934 memset(&m, 0, sizeof(m));
1935 m.tex[0] = R_GetTexture(layer->texture);
1936 m.texmatrix[0] = layer->texmatrix;
1937 m.texrgbscale[0] = layertexrgbscale;
1938 m.pointer_color = varray_color4f;
1940 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1942 surface = texturesurfacelist[texturesurfaceindex];
1943 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1944 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1945 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1946 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1947 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1948 GL_LockArrays(0, 0);
1951 case TEXTURELAYERTYPE_TEXTURE:
1952 memset(&m, 0, sizeof(m));
1953 m.tex[0] = R_GetTexture(layer->texture);
1954 m.texmatrix[0] = layer->texmatrix;
1955 m.pointer_color = varray_color4f;
1956 m.texrgbscale[0] = layertexrgbscale;
1958 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1960 surface = texturesurfacelist[texturesurfaceindex];
1961 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1962 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1963 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1964 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1965 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1966 GL_LockArrays(0, 0);
1969 case TEXTURELAYERTYPE_FOG:
1970 memset(&m, 0, sizeof(m));
1973 m.tex[0] = R_GetTexture(layer->texture);
1974 m.texmatrix[0] = layer->texmatrix;
1977 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1982 surface = texturesurfacelist[texturesurfaceindex];
1983 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1985 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1986 R_Mesh_ColorPointer(varray_color4f);
1987 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)
1989 VectorSubtract(v, modelorg, diff);
1990 f = exp(fogdensity/DotProduct(diff, diff));
1991 c[0] = layercolor[0];
1992 c[1] = layercolor[1];
1993 c[2] = layercolor[2];
1994 c[3] = f * layercolor[3];
1996 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1997 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1998 GL_LockArrays(0, 0);
2002 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2004 // if trying to do overbright on first pass of an opaque surface
2005 // when combine is not supported, brighten as a post process
2006 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2009 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2010 GL_Color(1, 1, 1, 1);
2011 memset(&m, 0, sizeof(m));
2013 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2015 surface = texturesurfacelist[texturesurfaceindex];
2016 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2017 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2018 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2019 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2020 GL_LockArrays(0, 0);
2025 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2026 qglEnable(GL_CULL_FACE);
2029 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2031 const entity_render_t *ent = (entity_render_t *)calldata1;
2032 const msurface_t *surface = ent->model->data_surfaces + calldata2;
2036 texture = surface->texture;
2037 if (texture->basematerialflags & MATERIALFLAG_SKY)
2038 return; // transparent sky is too difficult
2039 R_UpdateTextureInfo(ent, texture);
2041 R_Mesh_Matrix(&ent->matrix);
2042 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2043 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2046 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2048 int texturesurfaceindex;
2049 const msurface_t *surface;
2050 vec3_t tempcenter, center;
2051 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2053 // drawing sky transparently would be too difficult
2054 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2056 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2058 surface = texturesurfacelist[texturesurfaceindex];
2059 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2060 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2061 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2062 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2063 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2068 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2071 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2072 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2074 int i, j, f, flagsmask;
2075 int counttriangles = 0;
2076 msurface_t *surface, **surfacechain;
2077 texture_t *t, *texture;
2078 model_t *model = ent->model;
2080 const int maxsurfacelist = 1024;
2081 int numsurfacelist = 0;
2082 const msurface_t *surfacelist[1024];
2085 R_Mesh_Matrix(&ent->matrix);
2086 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2088 // update light styles
2089 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2091 for (i = 0;i < model->brushq1.light_styles;i++)
2093 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2095 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2096 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2097 for (;(surface = *surfacechain);surfacechain++)
2098 surface->cached_dlight = true;
2103 R_UpdateAllTextureInfo(ent);
2104 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2109 if (ent == r_refdef.worldentity)
2111 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2113 if (!r_worldsurfacevisible[j])
2115 if (t != surface->texture)
2119 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2122 t = surface->texture;
2123 texture = t->currentframe;
2124 f = texture->currentmaterialflags & flagsmask;
2126 if (f && surface->num_triangles)
2128 // if lightmap parameters changed, rebuild lightmap texture
2129 if (surface->cached_dlight && surface->lightmapinfo->samples)
2130 R_BuildLightMap(ent, surface);
2131 // add face to draw list
2132 surfacelist[numsurfacelist++] = surface;
2133 counttriangles += surface->num_triangles;
2134 if (numsurfacelist >= maxsurfacelist)
2136 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2144 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2146 if (t != surface->texture)
2150 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2153 t = surface->texture;
2154 texture = t->currentframe;
2155 f = texture->currentmaterialflags & flagsmask;
2157 if (f && surface->num_triangles)
2159 // if lightmap parameters changed, rebuild lightmap texture
2160 if (surface->cached_dlight && surface->lightmapinfo->samples)
2161 R_BuildLightMap(ent, surface);
2162 // add face to draw list
2163 surfacelist[numsurfacelist++] = surface;
2164 counttriangles += surface->num_triangles;
2165 if (numsurfacelist >= maxsurfacelist)
2167 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2174 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2175 if (!r_showtrispass)
2176 renderstats.entities_triangles += counttriangles;