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_shownormals = {0, "r_shownormals", "0"};
76 cvar_t r_drawentities = {0, "r_drawentities","1"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
78 cvar_t r_speeds = {0, "r_speeds","0"};
79 cvar_t r_fullbright = {0, "r_fullbright","0"};
80 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
81 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
82 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
83 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
85 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
86 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
87 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
88 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
89 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
90 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
91 cvar_t gl_fogend = {0, "gl_fogend","0"};
93 cvar_t r_textureunits = {0, "r_textureunits", "32"};
95 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
96 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
97 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
99 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0"};
100 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5"};
101 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4"};
102 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
103 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2"};
105 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1"};
107 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0"};
109 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
111 cvar_t r_test = {0, "r_test", "0"}; // used for testing renderer code changes, otherwise does nothing
113 rtexturepool_t *r_main_texturepool;
114 rtexture_t *r_bloom_texture_screen;
115 rtexture_t *r_bloom_texture_bloom;
116 rtexture_t *r_texture_blanknormalmap;
117 rtexture_t *r_texture_white;
118 rtexture_t *r_texture_black;
119 rtexture_t *r_texture_notexture;
120 rtexture_t *r_texture_whitecube;
121 rtexture_t *r_texture_normalizationcube;
122 rtexture_t *r_texture_fogattenuation;
123 rtexture_t *r_texture_fogintensity;
125 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
128 for (i = 0;i < verts;i++)
139 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
142 for (i = 0;i < verts;i++)
157 vec_t fogtabledistmultiplier;
158 float fogtable[FOGTABLEWIDTH];
159 float fog_density, fog_red, fog_green, fog_blue;
161 qboolean oldgl_fogenable;
162 void R_UpdateFog(void)
164 if (gamemode == GAME_NEHAHRA)
166 if (gl_fogenable.integer)
168 oldgl_fogenable = true;
169 fog_density = gl_fogdensity.value;
170 fog_red = gl_fogred.value;
171 fog_green = gl_foggreen.value;
172 fog_blue = gl_fogblue.value;
174 else if (oldgl_fogenable)
176 oldgl_fogenable = false;
185 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
186 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
187 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
192 fogdensity = -4000.0f / (fog_density * fog_density);
193 // this is the point where the fog reaches 0.9986 alpha, which we
194 // consider a good enough cutoff point for the texture
195 // (0.9986 * 256 == 255.6)
196 fogrange = 400 / fog_density;
197 fograngerecip = 1.0f / fogrange;
198 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
199 // fog color was already set
205 // FIXME: move this to client?
208 if (gamemode == GAME_NEHAHRA)
210 Cvar_Set("gl_fogenable", "0");
211 Cvar_Set("gl_fogdensity", "0.2");
212 Cvar_Set("gl_fogred", "0.3");
213 Cvar_Set("gl_foggreen", "0.3");
214 Cvar_Set("gl_fogblue", "0.3");
216 fog_density = fog_red = fog_green = fog_blue = 0.0f;
219 // FIXME: move this to client?
220 void FOG_registercvars(void)
225 if (gamemode == GAME_NEHAHRA)
227 Cvar_RegisterVariable (&gl_fogenable);
228 Cvar_RegisterVariable (&gl_fogdensity);
229 Cvar_RegisterVariable (&gl_fogred);
230 Cvar_RegisterVariable (&gl_foggreen);
231 Cvar_RegisterVariable (&gl_fogblue);
232 Cvar_RegisterVariable (&gl_fogstart);
233 Cvar_RegisterVariable (&gl_fogend);
236 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
237 for (x = 0;x < FOGTABLEWIDTH;x++)
239 alpha = exp(r / ((double)x*(double)x));
240 if (x == FOGTABLEWIDTH - 1)
242 fogtable[x] = bound(0, alpha, 1);
246 static void R_BuildBlankTextures(void)
248 unsigned char data[4];
249 data[0] = 128; // normal X
250 data[1] = 128; // normal Y
251 data[2] = 255; // normal Z
252 data[3] = 128; // height
253 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
258 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
263 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
266 static void R_BuildNoTexture(void)
269 unsigned char pix[16][16][4];
270 // this makes a light grey/dark grey checkerboard texture
271 for (y = 0;y < 16;y++)
273 for (x = 0;x < 16;x++)
275 if ((y < 8) ^ (x < 8))
291 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
294 static void R_BuildWhiteCube(void)
296 unsigned char data[6*1*1*4];
297 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
298 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
299 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
300 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
301 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
302 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
303 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
306 static void R_BuildNormalizationCube(void)
310 vec_t s, t, intensity;
312 unsigned char data[6][NORMSIZE][NORMSIZE][4];
313 for (side = 0;side < 6;side++)
315 for (y = 0;y < NORMSIZE;y++)
317 for (x = 0;x < NORMSIZE;x++)
319 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
320 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
355 intensity = 127.0f / sqrt(DotProduct(v, v));
356 data[side][y][x][0] = 128.0f + intensity * v[0];
357 data[side][y][x][1] = 128.0f + intensity * v[1];
358 data[side][y][x][2] = 128.0f + intensity * v[2];
359 data[side][y][x][3] = 255;
363 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
366 static void R_BuildFogTexture(void)
371 unsigned char data1[FOGWIDTH][4];
372 unsigned char data2[FOGWIDTH][4];
373 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
374 for (x = 0;x < FOGWIDTH;x++)
376 alpha = exp(r / ((double)x*(double)x));
377 if (x == FOGWIDTH - 1)
379 b = (int)(256.0 * alpha);
380 b = bound(0, b, 255);
381 data1[x][0] = 255 - b;
382 data1[x][1] = 255 - b;
383 data1[x][2] = 255 - b;
390 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
391 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
394 void gl_main_start(void)
396 r_main_texturepool = R_AllocTexturePool();
397 r_bloom_texture_screen = NULL;
398 r_bloom_texture_bloom = NULL;
399 R_BuildBlankTextures();
401 if (gl_texturecubemap)
404 R_BuildNormalizationCube();
409 void gl_main_shutdown(void)
411 R_FreeTexturePool(&r_main_texturepool);
412 r_bloom_texture_screen = NULL;
413 r_bloom_texture_bloom = NULL;
414 r_texture_blanknormalmap = NULL;
415 r_texture_white = NULL;
416 r_texture_black = NULL;
417 r_texture_whitecube = NULL;
418 r_texture_normalizationcube = NULL;
421 extern void CL_ParseEntityLump(char *entitystring);
422 void gl_main_newmap(void)
424 // FIXME: move this code to client
426 char *entities, entname[MAX_QPATH];
430 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
431 l = (int)strlen(entname) - 4;
432 if (l >= 0 && !strcmp(entname + l, ".bsp"))
434 strcpy(entname + l, ".ent");
435 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
437 CL_ParseEntityLump(entities);
442 if (cl.worldmodel->brush.entities)
443 CL_ParseEntityLump(cl.worldmodel->brush.entities);
447 void GL_Main_Init(void)
449 Matrix4x4_CreateIdentity(&r_identitymatrix);
450 // FIXME: move this to client?
452 Cvar_RegisterVariable(&r_showtris);
453 Cvar_RegisterVariable(&r_shownormals);
454 Cvar_RegisterVariable(&r_drawentities);
455 Cvar_RegisterVariable(&r_drawviewmodel);
456 Cvar_RegisterVariable(&r_speeds);
457 Cvar_RegisterVariable(&r_fullbrights);
458 Cvar_RegisterVariable(&r_wateralpha);
459 Cvar_RegisterVariable(&r_dynamic);
460 Cvar_RegisterVariable(&r_fullbright);
461 Cvar_RegisterVariable(&r_textureunits);
462 Cvar_RegisterVariable(&r_lerpsprites);
463 Cvar_RegisterVariable(&r_lerpmodels);
464 Cvar_RegisterVariable(&r_waterscroll);
465 Cvar_RegisterVariable(&r_drawcollisionbrushes);
466 Cvar_RegisterVariable(&r_bloom);
467 Cvar_RegisterVariable(&r_bloom_intensity);
468 Cvar_RegisterVariable(&r_bloom_blur);
469 Cvar_RegisterVariable(&r_bloom_resolution);
470 Cvar_RegisterVariable(&r_bloom_power);
471 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
472 Cvar_RegisterVariable(&developer_texturelogging);
473 Cvar_RegisterVariable(&gl_lightmaps);
474 Cvar_RegisterVariable(&r_test);
475 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
476 Cvar_SetValue("r_fullbrights", 0);
477 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
480 static vec3_t r_farclip_origin;
481 static vec3_t r_farclip_direction;
482 static vec_t r_farclip_directiondist;
483 static vec_t r_farclip_meshfarclip;
484 static int r_farclip_directionbit0;
485 static int r_farclip_directionbit1;
486 static int r_farclip_directionbit2;
488 // enlarge farclip to accomodate box
489 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
492 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
493 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
494 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
495 if (r_farclip_meshfarclip < d)
496 r_farclip_meshfarclip = d;
499 // return farclip value
500 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
504 VectorCopy(origin, r_farclip_origin);
505 VectorCopy(direction, r_farclip_direction);
506 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
507 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
508 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
509 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
510 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
512 if (r_refdef.worldmodel)
513 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
514 for (i = 0;i < r_refdef.numentities;i++)
515 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
517 return r_farclip_meshfarclip - r_farclip_directiondist;
520 extern void R_Textures_Init(void);
521 extern void GL_Draw_Init(void);
522 extern void GL_Main_Init(void);
523 extern void R_Shadow_Init(void);
524 extern void R_Sky_Init(void);
525 extern void GL_Surf_Init(void);
526 extern void R_Crosshairs_Init(void);
527 extern void R_Light_Init(void);
528 extern void R_Particles_Init(void);
529 extern void R_Explosion_Init(void);
530 extern void gl_backend_init(void);
531 extern void Sbar_Init(void);
532 extern void R_LightningBeams_Init(void);
533 extern void Mod_RenderInit(void);
535 void Render_Init(void)
551 R_LightningBeams_Init();
560 extern char *ENGINE_EXTENSIONS;
563 VID_CheckExtensions();
565 // LordHavoc: report supported extensions
566 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
568 // clear to black (loading plaque will be seen over this)
569 qglClearColor(0,0,0,1);
570 qglClear(GL_COLOR_BUFFER_BIT);
573 int R_CullBox(const vec3_t mins, const vec3_t maxs)
577 for (i = 0;i < 4;i++)
584 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
588 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
592 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
596 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
600 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
604 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
608 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
612 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
620 //==================================================================================
622 static void R_MarkEntities (void)
625 entity_render_t *ent;
627 if (!r_drawentities.integer)
630 r_refdef.worldentity->visframe = r_framecount;
631 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
632 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
634 // worldmodel can check visibility
635 for (i = 0;i < r_refdef.numentities;i++)
637 ent = r_refdef.entities[i];
638 // some of the renderer still relies on origin...
639 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
640 // some of the renderer still relies on scale...
641 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
642 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)))
644 R_UpdateEntLights(ent);
645 ent->visframe = r_framecount;
651 // no worldmodel or it can't check visibility
652 for (i = 0;i < r_refdef.numentities;i++)
654 ent = r_refdef.entities[i];
655 // some of the renderer still relies on origin...
656 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
657 // some of the renderer still relies on scale...
658 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
659 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
661 R_UpdateEntLights(ent);
662 ent->visframe = r_framecount;
668 // only used if skyrendermasked, and normally returns false
669 int R_DrawBrushModelsSky (void)
672 entity_render_t *ent;
674 if (!r_drawentities.integer)
678 for (i = 0;i < r_refdef.numentities;i++)
680 ent = r_refdef.entities[i];
681 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
683 ent->model->DrawSky(ent);
690 void R_DrawNoModel(entity_render_t *ent);
691 void R_DrawModels(void)
694 entity_render_t *ent;
696 if (!r_drawentities.integer)
699 for (i = 0;i < r_refdef.numentities;i++)
701 ent = r_refdef.entities[i];
702 if (ent->visframe == r_framecount)
704 renderstats.entities++;
705 if (ent->model && ent->model->Draw != NULL)
706 ent->model->Draw(ent);
713 static void R_SetFrustum(void)
715 // break apart the view matrix into vectors for various purposes
716 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
717 VectorNegate(r_viewleft, r_viewright);
719 // LordHavoc: note to all quake engine coders, the special case for 90
720 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
723 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
724 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
725 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
726 PlaneClassify(&frustum[0]);
728 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
729 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
730 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
731 PlaneClassify(&frustum[1]);
733 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
734 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
735 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
736 PlaneClassify(&frustum[2]);
738 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
739 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
740 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
741 PlaneClassify(&frustum[3]);
744 VectorCopy(r_viewforward, frustum[4].normal);
745 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
746 PlaneClassify(&frustum[4]);
749 static void R_BlendView(void)
751 int screenwidth, screenheight;
756 // set the (poorly named) screenwidth and screenheight variables to
757 // a power of 2 at least as large as the screen, these will define the
758 // size of the texture to allocate
759 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
760 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
762 doblend = r_refdef.viewblend[3] >= 0.01f;
763 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;
765 if (!dobloom && !doblend)
768 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
771 R_Mesh_Matrix(&r_identitymatrix);
772 // vertex coordinates for a quad that covers the screen exactly
773 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
774 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
775 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
776 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
779 int bloomwidth, bloomheight, x, dobloomblend, range;
780 float xoffset, yoffset, r;
782 // allocate textures as needed
783 if (!r_bloom_texture_screen)
784 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
785 if (!r_bloom_texture_bloom)
786 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
787 // set bloomwidth and bloomheight to the bloom resolution that will be
788 // used (often less than the screen resolution for faster rendering)
789 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
790 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
791 // set up a texcoord array for the full resolution screen image
792 // (we have to keep this around to copy back during final render)
793 varray_texcoord2f[0][0] = 0;
794 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
795 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
796 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
797 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
798 varray_texcoord2f[0][5] = 0;
799 varray_texcoord2f[0][6] = 0;
800 varray_texcoord2f[0][7] = 0;
801 // set up a texcoord array for the reduced resolution bloom image
802 // (which will be additive blended over the screen image)
803 varray_texcoord2f[1][0] = 0;
804 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
805 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
806 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
807 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
808 varray_texcoord2f[1][5] = 0;
809 varray_texcoord2f[1][6] = 0;
810 varray_texcoord2f[1][7] = 0;
811 memset(&m, 0, sizeof(m));
812 m.pointer_vertex = varray_vertex3f;
813 m.pointer_texcoord[0] = varray_texcoord2f[0];
814 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
816 // copy view into the full resolution screen image texture
818 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
819 renderstats.bloom_copypixels += r_view_width * r_view_height;
820 // now scale it down to the bloom size and raise to a power of itself
821 // to darken it (this leaves the really bright stuff bright, and
822 // everything else becomes very dark)
823 // TODO: optimize with multitexture or GLSL
824 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
825 GL_BlendFunc(GL_ONE, GL_ZERO);
826 GL_Color(1, 1, 1, 1);
827 R_Mesh_Draw(0, 4, 2, polygonelements);
828 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
829 // render multiple times with a multiply blendfunc to raise to a power
830 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
831 for (x = 1;x < r_bloom_power.integer;x++)
833 R_Mesh_Draw(0, 4, 2, polygonelements);
834 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
836 // we now have a darkened bloom image in the framebuffer, copy it into
837 // the bloom image texture for more processing
838 memset(&m, 0, sizeof(m));
839 m.pointer_vertex = varray_vertex3f;
840 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
841 m.pointer_texcoord[0] = varray_texcoord2f[2];
844 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
845 renderstats.bloom_copypixels += bloomwidth * bloomheight;
846 // blend on at multiple vertical offsets to achieve a vertical blur
847 // TODO: do offset blends using GLSL
848 range = r_bloom_blur.integer * bloomwidth / 320;
849 GL_BlendFunc(GL_ONE, GL_ZERO);
850 for (x = -range;x <= range;x++)
852 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
853 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
854 // compute a texcoord array with the specified x and y offset
855 varray_texcoord2f[2][0] = xoffset+0;
856 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
857 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
858 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
859 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
860 varray_texcoord2f[2][5] = yoffset+0;
861 varray_texcoord2f[2][6] = xoffset+0;
862 varray_texcoord2f[2][7] = yoffset+0;
863 // this r value looks like a 'dot' particle, fading sharply to
864 // black at the edges
865 // (probably not realistic but looks good enough)
866 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
869 GL_Color(r, r, r, 1);
870 R_Mesh_Draw(0, 4, 2, polygonelements);
871 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
872 GL_BlendFunc(GL_ONE, GL_ONE);
874 // copy the vertically blurred bloom view to a texture
876 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
877 renderstats.bloom_copypixels += bloomwidth * bloomheight;
878 // blend the vertically blurred image at multiple offsets horizontally
879 // to finish the blur effect
880 // TODO: do offset blends using GLSL
881 range = r_bloom_blur.integer * bloomwidth / 320;
882 GL_BlendFunc(GL_ONE, GL_ZERO);
883 for (x = -range;x <= range;x++)
885 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
886 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
887 // compute a texcoord array with the specified x and y offset
888 varray_texcoord2f[2][0] = xoffset+0;
889 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
890 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
891 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
892 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
893 varray_texcoord2f[2][5] = yoffset+0;
894 varray_texcoord2f[2][6] = xoffset+0;
895 varray_texcoord2f[2][7] = yoffset+0;
896 // this r value looks like a 'dot' particle, fading sharply to
897 // black at the edges
898 // (probably not realistic but looks good enough)
899 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
902 GL_Color(r, r, r, 1);
903 R_Mesh_Draw(0, 4, 2, polygonelements);
904 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
905 GL_BlendFunc(GL_ONE, GL_ONE);
907 // copy the blurred bloom view to a texture
909 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
910 renderstats.bloom_copypixels += bloomwidth * bloomheight;
911 // go back to full view area
912 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
913 // put the original screen image back in place and blend the bloom
915 memset(&m, 0, sizeof(m));
916 m.pointer_vertex = varray_vertex3f;
917 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
918 m.pointer_texcoord[0] = varray_texcoord2f[0];
920 dobloomblend = false;
922 // do both in one pass if possible
923 if (r_textureunits.integer >= 2 && gl_combine.integer)
925 dobloomblend = false;
926 m.texcombinergb[1] = GL_ADD;
927 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
928 m.pointer_texcoord[1] = varray_texcoord2f[1];
934 GL_BlendFunc(GL_ONE, GL_ZERO);
936 R_Mesh_Draw(0, 4, 2, polygonelements);
937 renderstats.bloom_drawpixels += r_view_width * r_view_height;
938 // now blend on the bloom texture if multipass
941 memset(&m, 0, sizeof(m));
942 m.pointer_vertex = varray_vertex3f;
943 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
944 m.pointer_texcoord[0] = varray_texcoord2f[1];
946 GL_BlendFunc(GL_ONE, GL_ONE);
948 R_Mesh_Draw(0, 4, 2, polygonelements);
949 renderstats.bloom_drawpixels += r_view_width * r_view_height;
954 // apply a color tint to the whole view
955 memset(&m, 0, sizeof(m));
956 m.pointer_vertex = varray_vertex3f;
958 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
959 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
960 R_Mesh_Draw(0, 4, 2, polygonelements);
964 void R_RenderScene(void);
966 matrix4x4_t r_waterscrollmatrix;
973 void R_RenderView(void)
975 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
976 return; //Host_Error ("R_RenderView: NULL worldmodel");
978 r_view_width = bound(0, r_refdef.width, vid.width);
979 r_view_height = bound(0, r_refdef.height, vid.height);
981 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
982 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
984 r_view_fov_x = bound(1, r_refdef.fov_x, 170);
985 r_view_fov_y = bound(1, r_refdef.fov_y, 170);
986 r_view_matrix = r_refdef.viewentitymatrix;
987 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
988 r_rtworld = r_shadow_realtime_world.integer;
989 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
990 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
991 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
992 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
994 // GL is weird because it's bottom to top, r_view_y is top to bottom
995 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
996 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
997 GL_ScissorTest(true);
1002 R_TimeReport("setup");
1004 qglDepthFunc(GL_LEQUAL);
1005 qglPolygonOffset(0, 0);
1006 qglEnable(GL_POLYGON_OFFSET_FILL);
1010 qglPolygonOffset(0, 0);
1011 qglDisable(GL_POLYGON_OFFSET_FILL);
1014 R_TimeReport("blendview");
1016 GL_Scissor(0, 0, vid.width, vid.height);
1017 GL_ScissorTest(false);
1020 extern void R_DrawLightningBeams (void);
1021 void R_RenderScene(void)
1023 // don't let sound skip if going slow
1024 if (r_refdef.extraupdate)
1029 R_MeshQueue_BeginScene();
1031 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1035 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1036 if (r_rtworldshadows || r_rtdlightshadows)
1037 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
1039 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
1041 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1043 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);
1047 R_WorldVisibility();
1048 R_TimeReport("worldvis");
1051 R_TimeReport("markentity");
1053 R_Shadow_UpdateWorldLightSelection();
1055 // don't let sound skip if going slow
1056 if (r_refdef.extraupdate)
1059 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1060 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1062 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1063 R_TimeReport("worldsky");
1066 if (R_DrawBrushModelsSky())
1067 R_TimeReport("bmodelsky");
1069 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1070 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1072 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1073 R_TimeReport("world");
1076 // don't let sound skip if going slow
1077 if (r_refdef.extraupdate)
1080 GL_ShowTrisColor(0, 0.015, 0, 1);
1083 R_TimeReport("models");
1085 // don't let sound skip if going slow
1086 if (r_refdef.extraupdate)
1089 GL_ShowTrisColor(0, 0, 0.033, 1);
1090 R_ShadowVolumeLighting(false);
1091 R_TimeReport("rtlights");
1093 // don't let sound skip if going slow
1094 if (r_refdef.extraupdate)
1097 GL_ShowTrisColor(0.1, 0, 0, 1);
1099 R_DrawLightningBeams();
1100 R_TimeReport("lightning");
1103 R_TimeReport("particles");
1106 R_TimeReport("explosions");
1108 R_MeshQueue_RenderTransparent();
1109 R_TimeReport("drawtrans");
1112 R_TimeReport("coronas");
1114 R_DrawWorldCrosshair();
1115 R_TimeReport("crosshair");
1117 R_MeshQueue_Render();
1118 R_MeshQueue_EndScene();
1120 if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1122 R_ShadowVolumeLighting(true);
1123 R_TimeReport("visiblevolume");
1126 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1128 // don't let sound skip if going slow
1129 if (r_refdef.extraupdate)
1134 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1137 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1139 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1140 GL_DepthMask(false);
1142 R_Mesh_Matrix(&r_identitymatrix);
1144 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1145 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1146 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1147 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1148 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1149 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1150 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1151 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1152 R_FillColors(color, 8, cr, cg, cb, ca);
1155 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1157 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1159 c[0] = c[0] * f1 + fogcolor[0] * f2;
1160 c[1] = c[1] * f1 + fogcolor[1] * f2;
1161 c[2] = c[2] * f1 + fogcolor[2] * f2;
1164 memset(&m, 0, sizeof(m));
1165 m.pointer_vertex = vertex3f;
1166 m.pointer_color = color;
1172 int nomodelelements[24] =
1184 float nomodelvertex3f[6*3] =
1194 float nomodelcolor4f[6*4] =
1196 0.0f, 0.0f, 0.5f, 1.0f,
1197 0.0f, 0.0f, 0.5f, 1.0f,
1198 0.0f, 0.5f, 0.0f, 1.0f,
1199 0.0f, 0.5f, 0.0f, 1.0f,
1200 0.5f, 0.0f, 0.0f, 1.0f,
1201 0.5f, 0.0f, 0.0f, 1.0f
1204 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1206 const entity_render_t *ent = (entity_render_t *)calldata1;
1211 R_Mesh_Matrix(&ent->matrix);
1213 memset(&m, 0, sizeof(m));
1214 m.pointer_vertex = nomodelvertex3f;
1216 if (ent->flags & EF_ADDITIVE)
1218 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1219 GL_DepthMask(false);
1221 else if (ent->alpha < 1)
1223 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1224 GL_DepthMask(false);
1228 GL_BlendFunc(GL_ONE, GL_ZERO);
1231 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1234 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1235 m.pointer_color = color4f;
1236 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1238 for (i = 0, c = color4f;i < 6;i++, c += 4)
1240 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1241 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1242 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1246 else if (ent->alpha != 1)
1248 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1249 m.pointer_color = color4f;
1250 for (i = 0, c = color4f;i < 6;i++, c += 4)
1254 m.pointer_color = nomodelcolor4f;
1256 R_Mesh_Draw(0, 6, 8, nomodelelements);
1259 void R_DrawNoModel(entity_render_t *ent)
1261 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1262 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1264 // R_DrawNoModelCallback(ent, 0);
1267 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1269 vec3_t right1, right2, diff, normal;
1271 VectorSubtract (org2, org1, normal);
1273 // calculate 'right' vector for start
1274 VectorSubtract (r_vieworigin, org1, diff);
1275 CrossProduct (normal, diff, right1);
1276 VectorNormalize (right1);
1278 // calculate 'right' vector for end
1279 VectorSubtract (r_vieworigin, org2, diff);
1280 CrossProduct (normal, diff, right2);
1281 VectorNormalize (right2);
1283 vert[ 0] = org1[0] + width * right1[0];
1284 vert[ 1] = org1[1] + width * right1[1];
1285 vert[ 2] = org1[2] + width * right1[2];
1286 vert[ 3] = org1[0] - width * right1[0];
1287 vert[ 4] = org1[1] - width * right1[1];
1288 vert[ 5] = org1[2] - width * right1[2];
1289 vert[ 6] = org2[0] - width * right2[0];
1290 vert[ 7] = org2[1] - width * right2[1];
1291 vert[ 8] = org2[2] - width * right2[2];
1292 vert[ 9] = org2[0] + width * right2[0];
1293 vert[10] = org2[1] + width * right2[1];
1294 vert[11] = org2[2] + width * right2[2];
1297 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1299 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)
1301 float fog = 0.0f, ifog;
1305 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1308 R_Mesh_Matrix(&r_identitymatrix);
1309 GL_BlendFunc(blendfunc1, blendfunc2);
1310 GL_DepthMask(false);
1311 GL_DepthTest(!depthdisable);
1313 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1314 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1315 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1316 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1317 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1318 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1319 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1320 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1321 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1322 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1323 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1324 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1326 memset(&m, 0, sizeof(m));
1327 m.tex[0] = R_GetTexture(texture);
1328 m.pointer_texcoord[0] = spritetexcoord2f;
1329 m.pointer_vertex = varray_vertex3f;
1331 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
1332 R_Mesh_Draw(0, 4, 2, polygonelements);
1334 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
1336 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
1337 GL_BlendFunc(blendfunc1, GL_ONE);
1338 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
1339 R_Mesh_Draw(0, 4, 2, polygonelements);
1343 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1347 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1348 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1350 if (i == mesh->numvertices)
1352 if (mesh->numvertices < mesh->maxvertices)
1354 VectorCopy(v, vertex3f);
1355 mesh->numvertices++;
1357 return mesh->numvertices;
1363 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1367 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1368 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1369 e = mesh->element3i + mesh->numtriangles * 3;
1370 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1372 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1373 if (mesh->numtriangles < mesh->maxtriangles)
1378 mesh->numtriangles++;
1380 element[1] = element[2];
1384 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1386 int planenum, planenum2;
1389 mplane_t *plane, *plane2;
1390 float temppoints[2][256*3];
1391 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1395 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1396 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1398 if (planenum2 == planenum)
1400 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);
1403 if (tempnumpoints < 3)
1405 // generate elements forming a triangle fan for this polygon
1406 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1410 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)
1412 texturelayer_t *layer;
1413 layer = t->currentlayers + t->currentnumlayers++;
1415 layer->depthmask = depthmask;
1416 layer->blendfunc1 = blendfunc1;
1417 layer->blendfunc2 = blendfunc2;
1418 layer->texture = texture;
1419 layer->texmatrix = *matrix;
1420 layer->color[0] = r;
1421 layer->color[1] = g;
1422 layer->color[2] = b;
1423 layer->color[3] = a;
1426 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1428 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1429 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1433 texture_t *texture = t;
1434 model_t *model = ent->model;
1435 int s = ent->skinnum;
1436 if ((unsigned int)s >= (unsigned int)model->numskins)
1438 if (model->skinscenes)
1440 if (model->skinscenes[s].framecount > 1)
1441 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1443 s = model->skinscenes[s].firstframe;
1446 t = t + s * model->num_surfaces;
1448 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];
1449 texture->currentframe = t;
1452 t->currentmaterialflags = t->basematerialflags;
1453 currentalpha = ent->alpha;
1454 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1455 currentalpha *= r_wateralpha.value;
1456 if (!(ent->flags & RENDER_LIGHT))
1457 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1458 if (ent->effects & EF_ADDITIVE)
1459 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1460 else if (currentalpha < 1)
1461 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1462 if (ent->effects & EF_NODEPTHTEST)
1463 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1464 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1465 t->currenttexmatrix = r_waterscrollmatrix;
1467 t->currenttexmatrix = r_identitymatrix;
1468 t->currentnumlayers = 0;
1469 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1471 if (gl_lightmaps.integer)
1472 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1473 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1475 // transparent sky would be ridiculous
1476 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1477 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1481 int blendfunc1, blendfunc2, depthmask;
1482 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1484 blendfunc1 = GL_SRC_ALPHA;
1485 blendfunc2 = GL_ONE;
1488 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1490 blendfunc1 = GL_SRC_ALPHA;
1491 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1496 blendfunc1 = GL_ONE;
1497 blendfunc2 = GL_ZERO;
1500 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1502 rtexture_t *currentbasetexture;
1504 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1505 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1506 currentbasetexture = (ent->colormap < 0 && t->skin.merged) ? t->skin.merged : t->skin.base;
1507 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1509 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], currentalpha);
1510 if (ent->colormap >= 0 && t->skin.pants)
1511 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);
1512 if (ent->colormap >= 0 && t->skin.shirt)
1513 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);
1519 // q3bsp has no lightmap updates, so the lightstylevalue that
1520 // would normally be baked into the lightmaptexture must be
1521 // applied to the color
1522 if (ent->model->type == mod_brushq3)
1523 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1524 // transparent and fullbright are not affected by r_lightmapintensity
1525 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1526 colorscale *= r_lightmapintensity;
1527 if (r_textureunits.integer >= 2 && gl_combine.integer)
1528 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);
1529 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1530 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);
1532 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);
1533 if (r_ambient.value >= (1.0f/64.0f))
1534 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);
1535 if (ent->colormap >= 0 && t->skin.pants)
1537 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);
1538 if (r_ambient.value >= (1.0f/64.0f))
1539 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);
1541 if (ent->colormap >= 0 && t->skin.shirt)
1543 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);
1544 if (r_ambient.value >= (1.0f/64.0f))
1545 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);
1548 if (t->skin.glow != NULL)
1549 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, currentalpha);
1550 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1552 // if this is opaque use alpha blend which will darken the earlier
1555 // if this is an alpha blended material, all the earlier passes
1556 // were darkened by fog already, so we only need to add the fog
1557 // color ontop through the fog mask texture
1559 // if this is an additive blended material, all the earlier passes
1560 // were darkened by fog already, and we should not add fog color
1561 // (because the background was not darkened, there is no fog color
1562 // that was lost behind it).
1563 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);
1570 void R_UpdateAllTextureInfo(entity_render_t *ent)
1574 for (i = 0;i < ent->model->num_textures;i++)
1575 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1578 float *rsurface_vertex3f;
1579 float *rsurface_svector3f;
1580 float *rsurface_tvector3f;
1581 float *rsurface_normal3f;
1582 float *rsurface_lightmapcolor4f;
1584 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1587 float center[3], forward[3], right[3], up[3], v[4][3];
1588 matrix4x4_t matrix1, imatrix1;
1589 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1591 rsurface_vertex3f = varray_vertex3f;
1592 rsurface_svector3f = NULL;
1593 rsurface_tvector3f = NULL;
1594 rsurface_normal3f = NULL;
1595 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1599 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1600 rsurface_svector3f = surface->groupmesh->data_svector3f;
1601 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1602 rsurface_normal3f = surface->groupmesh->data_normal3f;
1604 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1606 if (!rsurface_svector3f)
1608 rsurface_svector3f = varray_svector3f;
1609 rsurface_tvector3f = varray_tvector3f;
1610 rsurface_normal3f = varray_normal3f;
1611 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);
1613 // a single autosprite surface can contain multiple sprites...
1614 VectorClear(forward);
1616 VectorSet(up, 0, 0, 1);
1617 for (j = 0;j < surface->num_vertices - 3;j += 4)
1619 VectorClear(center);
1620 for (i = 0;i < 4;i++)
1621 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1622 VectorScale(center, 0.25f, center);
1623 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1624 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);
1625 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1626 for (i = 0;i < 4;i++)
1627 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1628 forward[0] = modelorg[0] - center[0];
1629 forward[1] = modelorg[1] - center[1];
1630 VectorNormalize(forward);
1631 right[0] = forward[1];
1632 right[1] = -forward[0];
1633 for (i = 0;i < 4;i++)
1634 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1636 rsurface_vertex3f = varray_vertex3f;
1637 rsurface_svector3f = NULL;
1638 rsurface_tvector3f = NULL;
1639 rsurface_normal3f = NULL;
1641 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1643 if (!rsurface_svector3f)
1645 rsurface_svector3f = varray_svector3f;
1646 rsurface_tvector3f = varray_tvector3f;
1647 rsurface_normal3f = varray_normal3f;
1648 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);
1650 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1651 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1652 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1653 // a single autosprite surface can contain multiple sprites...
1654 for (j = 0;j < surface->num_vertices - 3;j += 4)
1656 VectorClear(center);
1657 for (i = 0;i < 4;i++)
1658 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1659 VectorScale(center, 0.25f, center);
1660 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1661 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);
1662 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1663 for (i = 0;i < 4;i++)
1664 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1665 for (i = 0;i < 4;i++)
1666 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1668 rsurface_vertex3f = varray_vertex3f;
1669 rsurface_svector3f = NULL;
1670 rsurface_tvector3f = NULL;
1671 rsurface_normal3f = NULL;
1673 R_Mesh_VertexPointer(rsurface_vertex3f);
1676 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)
1684 vec4_t ambientcolor4f;
1685 vec3_t diffusecolor;
1686 vec3_t diffusenormal;
1687 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1689 rsurface_lightmapcolor4f = varray_color4f;
1690 if (rsurface_normal3f == NULL)
1692 rsurface_normal3f = varray_normal3f;
1693 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);
1695 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);
1704 r = ambientcolor4f[0];
1705 g = ambientcolor4f[1];
1706 b = ambientcolor4f[2];
1707 a = ambientcolor4f[3];
1708 rsurface_lightmapcolor4f = NULL;
1711 else if (lightmode >= 1)
1713 if (surface->lightmapinfo)
1715 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1717 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1720 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1721 VectorScale(lm, scale, c);
1722 if (surface->lightmapinfo->styles[1] != 255)
1724 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1726 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1727 VectorMA(c, scale, lm, c);
1728 if (surface->lightmapinfo->styles[2] != 255)
1731 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1732 VectorMA(c, scale, lm, c);
1733 if (surface->lightmapinfo->styles[3] != 255)
1736 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1737 VectorMA(c, scale, lm, c);
1745 rsurface_lightmapcolor4f = varray_color4f;
1748 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1751 rsurface_lightmapcolor4f = NULL;
1754 if (rsurface_lightmapcolor4f)
1756 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)
1758 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1767 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)
1769 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1776 rsurface_lightmapcolor4f = varray_color4f;
1778 if (applycolor && rsurface_lightmapcolor4f)
1780 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)
1787 rsurface_lightmapcolor4f = varray_color4f;
1789 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1790 GL_Color(r, g, b, a);
1793 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1795 int texturesurfaceindex;
1797 const msurface_t *surface;
1798 qboolean applycolor;
1800 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1802 renderstats.entities_surfaces += texturenumsurfaces;
1803 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1804 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1805 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1806 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1807 qglDisable(GL_CULL_FACE);
1808 if (texture->currentnumlayers)
1811 texturelayer_t *layer;
1812 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1815 int layertexrgbscale;
1816 GL_DepthMask(layer->depthmask);
1817 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1818 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1820 layertexrgbscale = 4;
1821 VectorScale(layer->color, 0.25f, layercolor);
1823 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
1825 layertexrgbscale = 2;
1826 VectorScale(layer->color, 0.5f, layercolor);
1830 layertexrgbscale = 1;
1831 VectorScale(layer->color, 1.0f, layercolor);
1833 layercolor[3] = layer->color[3];
1834 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1835 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
1836 switch (layer->type)
1838 case TEXTURELAYERTYPE_SKY:
1841 skyrendernow = false;
1842 if (skyrendermasked)
1845 // restore entity matrix and GL_Color
1846 R_Mesh_Matrix(&ent->matrix);
1847 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1850 // LordHavoc: HalfLife maps have freaky skypolys...
1851 //if (!ent->model->brush.ishlbsp)
1853 if (skyrendermasked)
1855 // depth-only (masking)
1856 GL_ColorMask(0,0,0,0);
1857 // just to make sure that braindead drivers don't draw anything
1858 // despite that colormask...
1859 GL_BlendFunc(GL_ZERO, GL_ONE);
1864 GL_BlendFunc(GL_ONE, GL_ZERO);
1866 memset(&m, 0, sizeof(m));
1868 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1870 surface = texturesurfacelist[texturesurfaceindex];
1871 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1872 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1873 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1874 GL_LockArrays(0, 0);
1876 if (skyrendermasked)
1877 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1880 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
1881 memset(&m, 0, sizeof(m));
1882 m.tex[1] = R_GetTexture(layer->texture);
1883 m.texmatrix[1] = layer->texmatrix;
1884 m.texrgbscale[1] = layertexrgbscale;
1885 m.pointer_color = varray_color4f;
1887 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1889 surface = texturesurfacelist[texturesurfaceindex];
1890 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1891 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1892 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1895 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1896 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1898 else if (surface->lightmaptexture)
1900 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1901 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1905 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1906 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1908 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1909 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1910 GL_LockArrays(0, 0);
1913 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
1914 memset(&m, 0, sizeof(m));
1915 m.tex[0] = R_GetTexture(layer->texture);
1916 m.texmatrix[0] = layer->texmatrix;
1917 m.pointer_color = varray_color4f;
1918 m.texrgbscale[0] = layertexrgbscale;
1920 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1922 surface = texturesurfacelist[texturesurfaceindex];
1923 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1924 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1927 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1928 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
1930 else if (surface->lightmaptexture)
1932 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1933 R_Mesh_ColorPointer(NULL);
1937 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1938 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
1940 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1941 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1942 GL_LockArrays(0, 0);
1944 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1945 memset(&m, 0, sizeof(m));
1946 m.tex[0] = R_GetTexture(layer->texture);
1947 m.texmatrix[0] = layer->texmatrix;
1948 m.pointer_color = varray_color4f;
1949 m.texrgbscale[0] = layertexrgbscale;
1951 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1953 surface = texturesurfacelist[texturesurfaceindex];
1954 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1955 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1956 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1957 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1958 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1959 GL_LockArrays(0, 0);
1962 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
1963 memset(&m, 0, sizeof(m));
1964 m.tex[0] = R_GetTexture(layer->texture);
1965 m.texmatrix[0] = layer->texmatrix;
1966 m.texrgbscale[0] = layertexrgbscale;
1967 m.pointer_color = varray_color4f;
1969 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1971 surface = texturesurfacelist[texturesurfaceindex];
1972 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1973 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1974 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1975 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1976 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1977 GL_LockArrays(0, 0);
1980 case TEXTURELAYERTYPE_TEXTURE:
1981 memset(&m, 0, sizeof(m));
1982 m.tex[0] = R_GetTexture(layer->texture);
1983 m.texmatrix[0] = layer->texmatrix;
1984 m.pointer_color = varray_color4f;
1985 m.texrgbscale[0] = layertexrgbscale;
1987 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1989 surface = texturesurfacelist[texturesurfaceindex];
1990 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1991 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1992 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1993 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1994 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1995 GL_LockArrays(0, 0);
1998 case TEXTURELAYERTYPE_FOG:
1999 memset(&m, 0, sizeof(m));
2002 m.tex[0] = R_GetTexture(layer->texture);
2003 m.texmatrix[0] = layer->texmatrix;
2006 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2010 surface = texturesurfacelist[texturesurfaceindex];
2011 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2013 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2014 R_Mesh_ColorPointer(varray_color4f);
2015 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)
2017 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2018 c[0] = layercolor[0];
2019 c[1] = layercolor[1];
2020 c[2] = layercolor[2];
2021 c[3] = f * layercolor[3];
2023 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2024 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2025 GL_LockArrays(0, 0);
2029 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2031 // if trying to do overbright on first pass of an opaque surface
2032 // when combine is not supported, brighten as a post process
2033 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2036 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2037 GL_Color(1, 1, 1, 1);
2038 memset(&m, 0, sizeof(m));
2040 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2042 surface = texturesurfacelist[texturesurfaceindex];
2043 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2044 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2045 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2046 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2047 GL_LockArrays(0, 0);
2051 if (r_shownormals.integer && !r_showtrispass)
2056 GL_DepthMask(texture->currentlayers->depthmask);
2057 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
2058 memset(&m, 0, sizeof(m));
2060 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2062 surface = texturesurfacelist[texturesurfaceindex];
2063 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2064 if (!rsurface_svector3f)
2066 rsurface_svector3f = varray_svector3f;
2067 rsurface_tvector3f = varray_tvector3f;
2068 rsurface_normal3f = varray_normal3f;
2069 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);
2071 GL_Color(1, 0, 0, 1);
2073 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2075 VectorCopy(rsurface_vertex3f + k * 3, v);
2076 qglVertex3f(v[0], v[1], v[2]);
2077 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
2078 qglVertex3f(v[0], v[1], v[2]);
2080 GL_Color(0, 0, 1, 1);
2081 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2083 VectorCopy(rsurface_vertex3f + k * 3, v);
2084 qglVertex3f(v[0], v[1], v[2]);
2085 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
2086 qglVertex3f(v[0], v[1], v[2]);
2088 GL_Color(0, 1, 0, 1);
2089 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2091 VectorCopy(rsurface_vertex3f + k * 3, v);
2092 qglVertex3f(v[0], v[1], v[2]);
2093 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
2094 qglVertex3f(v[0], v[1], v[2]);
2100 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2101 qglEnable(GL_CULL_FACE);
2104 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2106 const entity_render_t *ent = (entity_render_t *)calldata1;
2107 const msurface_t *surface = ent->model->data_surfaces + calldata2;
2111 texture = surface->texture;
2112 if (texture->basematerialflags & MATERIALFLAG_SKY)
2113 return; // transparent sky is too difficult
2114 R_UpdateTextureInfo(ent, texture);
2116 R_Mesh_Matrix(&ent->matrix);
2117 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2118 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2121 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2123 int texturesurfaceindex;
2124 const msurface_t *surface;
2125 vec3_t tempcenter, center;
2126 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2128 // drawing sky transparently would be too difficult
2129 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2131 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2133 surface = texturesurfacelist[texturesurfaceindex];
2134 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2135 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2136 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2137 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2138 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2143 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2146 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2147 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2149 int i, j, f, flagsmask;
2150 int counttriangles = 0;
2151 msurface_t *surface, **surfacechain;
2152 texture_t *t, *texture;
2153 model_t *model = ent->model;
2155 const int maxsurfacelist = 1024;
2156 int numsurfacelist = 0;
2157 const msurface_t *surfacelist[1024];
2160 R_Mesh_Matrix(&ent->matrix);
2161 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2163 // update light styles
2164 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2166 for (i = 0;i < model->brushq1.light_styles;i++)
2168 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2170 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2171 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2172 for (;(surface = *surfacechain);surfacechain++)
2173 surface->cached_dlight = true;
2178 R_UpdateAllTextureInfo(ent);
2179 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2184 if (ent == r_refdef.worldentity)
2186 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2188 if (!r_worldsurfacevisible[j])
2190 if (t != surface->texture)
2194 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2197 t = surface->texture;
2198 texture = t->currentframe;
2199 f = texture->currentmaterialflags & flagsmask;
2201 if (f && surface->num_triangles)
2203 // if lightmap parameters changed, rebuild lightmap texture
2204 if (surface->cached_dlight && surface->lightmapinfo->samples)
2205 R_BuildLightMap(ent, surface);
2206 // add face to draw list
2207 surfacelist[numsurfacelist++] = surface;
2208 counttriangles += surface->num_triangles;
2209 if (numsurfacelist >= maxsurfacelist)
2211 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2219 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2221 if (t != surface->texture)
2225 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2228 t = surface->texture;
2229 texture = t->currentframe;
2230 f = texture->currentmaterialflags & flagsmask;
2232 if (f && surface->num_triangles)
2234 // if lightmap parameters changed, rebuild lightmap texture
2235 if (surface->cached_dlight && surface->lightmapinfo->samples)
2236 R_BuildLightMap(ent, surface);
2237 // add face to draw list
2238 surfacelist[numsurfacelist++] = surface;
2239 counttriangles += surface->num_triangles;
2240 if (numsurfacelist >= maxsurfacelist)
2242 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2249 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2250 if (!r_showtrispass)
2251 renderstats.entities_triangles += counttriangles;