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 // 8.8 fraction of base light value
75 unsigned short d_lightstylevalue[256];
77 cvar_t r_showtris = {0, "r_showtris", "0"};
78 cvar_t r_drawentities = {0, "r_drawentities","1"};
79 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
80 cvar_t r_speeds = {0, "r_speeds","0"};
81 cvar_t r_fullbright = {0, "r_fullbright","0"};
82 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
83 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
84 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
85 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
87 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
88 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
89 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
90 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
91 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
92 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
93 cvar_t gl_fogend = {0, "gl_fogend","0"};
95 cvar_t r_textureunits = {0, "r_textureunits", "32"};
97 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
98 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
99 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
101 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0"};
102 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "2"};
103 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "8"};
104 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
105 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"};
107 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1"};
109 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0"};
111 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
113 cvar_t r_test = {0, "r_test", "0"}; // used for testing renderer code changes, otherwise does nothing
115 rtexturepool_t *r_main_texturepool;
116 rtexture_t *r_bloom_texture_screen;
117 rtexture_t *r_bloom_texture_bloom;
118 rtexture_t *r_texture_blanknormalmap;
119 rtexture_t *r_texture_white;
120 rtexture_t *r_texture_black;
121 rtexture_t *r_texture_notexture;
122 rtexture_t *r_texture_whitecube;
123 rtexture_t *r_texture_normalizationcube;
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++)
154 float fog_density, fog_red, fog_green, fog_blue;
156 qboolean oldgl_fogenable;
157 void R_UpdateFog(void)
159 if (gamemode == GAME_NEHAHRA)
161 if (gl_fogenable.integer)
163 oldgl_fogenable = true;
164 fog_density = gl_fogdensity.value;
165 fog_red = gl_fogred.value;
166 fog_green = gl_foggreen.value;
167 fog_blue = gl_fogblue.value;
169 else if (oldgl_fogenable)
171 oldgl_fogenable = false;
180 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
181 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
182 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
187 fogdensity = -4000.0f / (fog_density * fog_density);
188 // fog color was already set
194 // FIXME: move this to client?
197 if (gamemode == GAME_NEHAHRA)
199 Cvar_Set("gl_fogenable", "0");
200 Cvar_Set("gl_fogdensity", "0.2");
201 Cvar_Set("gl_fogred", "0.3");
202 Cvar_Set("gl_foggreen", "0.3");
203 Cvar_Set("gl_fogblue", "0.3");
205 fog_density = fog_red = fog_green = fog_blue = 0.0f;
208 // FIXME: move this to client?
209 void FOG_registercvars(void)
211 if (gamemode == GAME_NEHAHRA)
213 Cvar_RegisterVariable (&gl_fogenable);
214 Cvar_RegisterVariable (&gl_fogdensity);
215 Cvar_RegisterVariable (&gl_fogred);
216 Cvar_RegisterVariable (&gl_foggreen);
217 Cvar_RegisterVariable (&gl_fogblue);
218 Cvar_RegisterVariable (&gl_fogstart);
219 Cvar_RegisterVariable (&gl_fogend);
223 static void R_BuildBlankTextures(void)
226 data[0] = 128; // normal X
227 data[1] = 128; // normal Y
228 data[2] = 255; // normal Z
229 data[3] = 128; // height
230 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
235 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
240 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
243 static void R_BuildNoTexture(void)
246 qbyte pix[16][16][4];
247 // this makes a light grey/dark grey checkerboard texture
248 for (y = 0;y < 16;y++)
250 for (x = 0;x < 16;x++)
252 if ((y < 8) ^ (x < 8))
268 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
271 static void R_BuildWhiteCube(void)
274 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
275 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
276 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
277 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
278 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
279 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
280 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
283 static void R_BuildNormalizationCube(void)
287 vec_t s, t, intensity;
289 qbyte data[6][NORMSIZE][NORMSIZE][4];
290 for (side = 0;side < 6;side++)
292 for (y = 0;y < NORMSIZE;y++)
294 for (x = 0;x < NORMSIZE;x++)
296 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
297 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
332 intensity = 127.0f / sqrt(DotProduct(v, v));
333 data[side][y][x][0] = 128.0f + intensity * v[0];
334 data[side][y][x][1] = 128.0f + intensity * v[1];
335 data[side][y][x][2] = 128.0f + intensity * v[2];
336 data[side][y][x][3] = 255;
340 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
343 void gl_main_start(void)
345 r_main_texturepool = R_AllocTexturePool();
346 r_bloom_texture_screen = NULL;
347 r_bloom_texture_bloom = NULL;
348 R_BuildBlankTextures();
350 if (gl_texturecubemap)
353 R_BuildNormalizationCube();
357 void gl_main_shutdown(void)
359 R_FreeTexturePool(&r_main_texturepool);
360 r_bloom_texture_screen = NULL;
361 r_bloom_texture_bloom = NULL;
362 r_texture_blanknormalmap = NULL;
363 r_texture_white = NULL;
364 r_texture_black = NULL;
365 r_texture_whitecube = NULL;
366 r_texture_normalizationcube = NULL;
369 extern void CL_ParseEntityLump(char *entitystring);
370 void gl_main_newmap(void)
372 // FIXME: move this code to client
374 char *entities, entname[MAX_QPATH];
378 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
379 l = (int)strlen(entname) - 4;
380 if (l >= 0 && !strcmp(entname + l, ".bsp"))
382 strcpy(entname + l, ".ent");
383 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true)))
385 CL_ParseEntityLump(entities);
390 if (cl.worldmodel->brush.entities)
391 CL_ParseEntityLump(cl.worldmodel->brush.entities);
395 void GL_Main_Init(void)
397 Matrix4x4_CreateIdentity(&r_identitymatrix);
398 // FIXME: move this to client?
400 Cvar_RegisterVariable(&r_showtris);
401 Cvar_RegisterVariable(&r_drawentities);
402 Cvar_RegisterVariable(&r_drawviewmodel);
403 Cvar_RegisterVariable(&r_speeds);
404 Cvar_RegisterVariable(&r_fullbrights);
405 Cvar_RegisterVariable(&r_wateralpha);
406 Cvar_RegisterVariable(&r_dynamic);
407 Cvar_RegisterVariable(&r_fullbright);
408 Cvar_RegisterVariable(&r_textureunits);
409 Cvar_RegisterVariable(&r_lerpsprites);
410 Cvar_RegisterVariable(&r_lerpmodels);
411 Cvar_RegisterVariable(&r_waterscroll);
412 Cvar_RegisterVariable(&r_drawcollisionbrushes);
413 Cvar_RegisterVariable(&r_bloom);
414 Cvar_RegisterVariable(&r_bloom_intensity);
415 Cvar_RegisterVariable(&r_bloom_blur);
416 Cvar_RegisterVariable(&r_bloom_resolution);
417 Cvar_RegisterVariable(&r_bloom_power);
418 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
419 Cvar_RegisterVariable(&developer_texturelogging);
420 Cvar_RegisterVariable(&gl_lightmaps);
421 Cvar_RegisterVariable(&r_test);
422 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
423 Cvar_SetValue("r_fullbrights", 0);
424 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
427 static vec3_t r_farclip_origin;
428 static vec3_t r_farclip_direction;
429 static vec_t r_farclip_directiondist;
430 static vec_t r_farclip_meshfarclip;
431 static int r_farclip_directionbit0;
432 static int r_farclip_directionbit1;
433 static int r_farclip_directionbit2;
435 // enlarge farclip to accomodate box
436 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
439 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
440 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
441 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
442 if (r_farclip_meshfarclip < d)
443 r_farclip_meshfarclip = d;
446 // return farclip value
447 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
451 VectorCopy(origin, r_farclip_origin);
452 VectorCopy(direction, r_farclip_direction);
453 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
454 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
455 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
456 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
457 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
459 if (r_refdef.worldmodel)
460 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
461 for (i = 0;i < r_refdef.numentities;i++)
462 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
464 return r_farclip_meshfarclip - r_farclip_directiondist;
467 extern void R_Textures_Init(void);
468 extern void GL_Draw_Init(void);
469 extern void GL_Main_Init(void);
470 extern void R_Shadow_Init(void);
471 extern void R_Sky_Init(void);
472 extern void GL_Surf_Init(void);
473 extern void R_Crosshairs_Init(void);
474 extern void R_Light_Init(void);
475 extern void R_Particles_Init(void);
476 extern void R_Explosion_Init(void);
477 extern void gl_backend_init(void);
478 extern void Sbar_Init(void);
479 extern void R_LightningBeams_Init(void);
480 extern void Mod_RenderInit(void);
482 void Render_Init(void)
498 R_LightningBeams_Init();
507 extern char *ENGINE_EXTENSIONS;
510 VID_CheckExtensions();
512 // LordHavoc: report supported extensions
513 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
515 // clear to black (loading plaque will be seen over this)
516 qglClearColor(0,0,0,1);
517 qglClear(GL_COLOR_BUFFER_BIT);
520 int R_CullBox(const vec3_t mins, const vec3_t maxs)
524 for (i = 0;i < 4;i++)
531 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
535 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
539 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
543 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
547 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
551 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
555 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
559 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
567 //==================================================================================
569 static void R_MarkEntities (void)
572 entity_render_t *ent;
574 if (!r_drawentities.integer)
577 r_refdef.worldentity->visframe = r_framecount;
578 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
579 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
581 // worldmodel can check visibility
582 for (i = 0;i < r_refdef.numentities;i++)
584 ent = r_refdef.entities[i];
585 Mod_CheckLoaded(ent->model);
586 // some of the renderer still relies on origin...
587 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
588 // some of the renderer still relies on scale...
589 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
590 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)))
592 R_UpdateEntLights(ent);
593 ent->visframe = r_framecount;
599 // no worldmodel or it can't check visibility
600 for (i = 0;i < r_refdef.numentities;i++)
602 ent = r_refdef.entities[i];
603 Mod_CheckLoaded(ent->model);
604 // some of the renderer still relies on origin...
605 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
606 // some of the renderer still relies on scale...
607 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
608 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
610 R_UpdateEntLights(ent);
611 ent->visframe = r_framecount;
617 // only used if skyrendermasked, and normally returns false
618 int R_DrawBrushModelsSky (void)
621 entity_render_t *ent;
623 if (!r_drawentities.integer)
627 for (i = 0;i < r_refdef.numentities;i++)
629 ent = r_refdef.entities[i];
630 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
632 ent->model->DrawSky(ent);
639 void R_DrawNoModel(entity_render_t *ent);
640 void R_DrawModels(void)
643 entity_render_t *ent;
645 if (!r_drawentities.integer)
648 for (i = 0;i < r_refdef.numentities;i++)
650 ent = r_refdef.entities[i];
651 if (ent->visframe == r_framecount)
653 renderstats.entities++;
654 if (ent->model && ent->model->Draw != NULL)
655 ent->model->Draw(ent);
662 static void R_SetFrustum(void)
664 // break apart the view matrix into vectors for various purposes
665 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
666 VectorNegate(r_viewleft, r_viewright);
668 // LordHavoc: note to all quake engine coders, the special case for 90
669 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
672 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
673 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
674 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
675 PlaneClassify(&frustum[0]);
677 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
678 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
679 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
680 PlaneClassify(&frustum[1]);
682 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
683 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
684 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
685 PlaneClassify(&frustum[2]);
687 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
688 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
689 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
690 PlaneClassify(&frustum[3]);
693 VectorCopy(r_viewforward, frustum[4].normal);
694 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
695 PlaneClassify(&frustum[4]);
698 static void R_BlendView(void)
702 if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
705 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
708 R_Mesh_Matrix(&r_identitymatrix);
709 // vertex coordinates for a quad that covers the screen exactly
710 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
711 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
712 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
713 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
714 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)
716 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
717 float xoffset, yoffset, r;
719 // set the (poorly named) screenwidth and screenheight variables to
720 // a power of 2 at least as large as the screen, these will define the
721 // size of the texture to allocate
722 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
723 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
724 // allocate textures as needed
725 if (!r_bloom_texture_screen)
726 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
727 if (!r_bloom_texture_bloom)
728 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
729 // set bloomwidth and bloomheight to the bloom resolution that will be
730 // used (often less than the screen resolution for faster rendering)
731 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
732 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
733 // set up a texcoord array for the full resolution screen image
734 // (we have to keep this around to copy back during final render)
735 varray_texcoord2f[0][0] = 0;
736 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
737 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
738 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
739 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
740 varray_texcoord2f[0][5] = 0;
741 varray_texcoord2f[0][6] = 0;
742 varray_texcoord2f[0][7] = 0;
743 // set up a texcoord array for the reduced resolution bloom image
744 // (which will be additive blended over the screen image)
745 varray_texcoord2f[1][0] = 0;
746 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
747 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
748 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
749 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
750 varray_texcoord2f[1][5] = 0;
751 varray_texcoord2f[1][6] = 0;
752 varray_texcoord2f[1][7] = 0;
753 memset(&m, 0, sizeof(m));
754 m.pointer_vertex = varray_vertex3f;
755 m.pointer_texcoord[0] = varray_texcoord2f[0];
756 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
758 // copy view into the full resolution screen image texture
760 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
761 renderstats.bloom_copypixels += r_view_width * r_view_height;
762 // now scale it down to the bloom size and raise to a power of itself
763 // to darken it (this leaves the really bright stuff bright, and
764 // everything else becomes very dark)
765 // TODO: optimize with multitexture or GLSL
766 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
767 GL_BlendFunc(GL_ONE, GL_ZERO);
768 GL_Color(1, 1, 1, 1);
769 R_Mesh_Draw(0, 4, 2, polygonelements);
770 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
771 // render multiple times with a multiply blendfunc to raise to a power
772 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
773 for (x = 1;x < r_bloom_power.integer;x++)
775 R_Mesh_Draw(0, 4, 2, polygonelements);
776 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
778 // we now have a darkened bloom image in the framebuffer, copy it into
779 // the bloom image texture for more processing
780 memset(&m, 0, sizeof(m));
781 m.pointer_vertex = varray_vertex3f;
782 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
783 m.pointer_texcoord[0] = varray_texcoord2f[2];
786 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
787 renderstats.bloom_copypixels += bloomwidth * bloomheight;
788 // blend on at multiple vertical offsets to achieve a vertical blur
789 // TODO: do offset blends using GLSL
790 range = r_bloom_blur.integer * bloomwidth / 320;
791 GL_BlendFunc(GL_ONE, GL_ZERO);
792 for (x = -range;x <= range;x++)
794 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
795 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
796 // compute a texcoord array with the specified x and y offset
797 varray_texcoord2f[2][0] = xoffset+0;
798 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
799 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
800 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
801 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
802 varray_texcoord2f[2][5] = yoffset+0;
803 varray_texcoord2f[2][6] = xoffset+0;
804 varray_texcoord2f[2][7] = yoffset+0;
805 // this r value looks like a 'dot' particle, fading sharply to
806 // black at the edges
807 // (probably not realistic but looks good enough)
808 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
811 GL_Color(r, r, r, 1);
812 R_Mesh_Draw(0, 4, 2, polygonelements);
813 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
814 GL_BlendFunc(GL_ONE, GL_ONE);
816 // copy the vertically blurred bloom view to a texture
818 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
819 renderstats.bloom_copypixels += bloomwidth * bloomheight;
820 // blend the vertically blurred image at multiple offsets horizontally
821 // to finish the blur effect
822 // TODO: do offset blends using GLSL
823 range = r_bloom_blur.integer * bloomwidth / 320;
824 GL_BlendFunc(GL_ONE, GL_ZERO);
825 for (x = -range;x <= range;x++)
827 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
828 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
829 // compute a texcoord array with the specified x and y offset
830 varray_texcoord2f[2][0] = xoffset+0;
831 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
832 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
833 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
834 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
835 varray_texcoord2f[2][5] = yoffset+0;
836 varray_texcoord2f[2][6] = xoffset+0;
837 varray_texcoord2f[2][7] = yoffset+0;
838 // this r value looks like a 'dot' particle, fading sharply to
839 // black at the edges
840 // (probably not realistic but looks good enough)
841 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
844 GL_Color(r, r, r, 1);
845 R_Mesh_Draw(0, 4, 2, polygonelements);
846 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
847 GL_BlendFunc(GL_ONE, GL_ONE);
849 // copy the blurred bloom view to a texture
851 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
852 renderstats.bloom_copypixels += bloomwidth * bloomheight;
853 // go back to full view area
854 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
855 // put the original screen image back in place and blend the bloom
857 memset(&m, 0, sizeof(m));
858 m.pointer_vertex = varray_vertex3f;
859 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
860 m.pointer_texcoord[0] = varray_texcoord2f[0];
862 dobloomblend = false;
864 // do both in one pass if possible
865 if (r_textureunits.integer >= 2 && gl_combine.integer)
867 dobloomblend = false;
868 m.texcombinergb[1] = GL_ADD;
869 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
870 m.pointer_texcoord[1] = varray_texcoord2f[1];
876 GL_BlendFunc(GL_ONE, GL_ZERO);
878 R_Mesh_Draw(0, 4, 2, polygonelements);
879 renderstats.bloom_drawpixels += r_view_width * r_view_height;
880 // now blend on the bloom texture if multipass
883 memset(&m, 0, sizeof(m));
884 m.pointer_vertex = varray_vertex3f;
885 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
886 m.pointer_texcoord[0] = varray_texcoord2f[1];
888 GL_BlendFunc(GL_ONE, GL_ONE);
890 R_Mesh_Draw(0, 4, 2, polygonelements);
891 renderstats.bloom_drawpixels += r_view_width * r_view_height;
894 if (r_refdef.viewblend[3] >= 0.01f)
896 // apply a color tint to the whole view
897 memset(&m, 0, sizeof(m));
898 m.pointer_vertex = varray_vertex3f;
900 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
901 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
902 R_Mesh_Draw(0, 4, 2, polygonelements);
906 void R_RenderScene(void);
908 matrix4x4_t r_waterscrollmatrix;
915 void R_RenderView(void)
917 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
918 return; //Host_Error ("R_RenderView: NULL worldmodel");
920 r_view_width = bound(0, r_refdef.width, vid.width);
921 r_view_height = bound(0, r_refdef.height, vid.height);
923 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
924 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
926 r_view_fov_x = bound(1, r_refdef.fov_x, 170);
927 r_view_fov_y = bound(1, r_refdef.fov_y, 170);
928 r_view_matrix = r_refdef.viewentitymatrix;
929 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
930 r_rtworld = r_shadow_realtime_world.integer;
931 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
932 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
933 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
934 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
936 // GL is weird because it's bottom to top, r_view_y is top to bottom
937 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
938 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
939 GL_ScissorTest(true);
945 R_TimeReport("setup");
947 qglDepthFunc(GL_LEQUAL);
948 qglPolygonOffset(0, 0);
949 qglEnable(GL_POLYGON_OFFSET_FILL);
953 qglPolygonOffset(0, 0);
954 qglDisable(GL_POLYGON_OFFSET_FILL);
957 R_TimeReport("blendview");
959 GL_Scissor(0, 0, vid.width, vid.height);
960 GL_ScissorTest(false);
963 extern void R_DrawLightningBeams (void);
964 void R_RenderScene(void)
966 // don't let sound skip if going slow
967 if (r_refdef.extraupdate)
972 R_MeshQueue_BeginScene();
974 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
978 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
979 if (r_rtworldshadows || r_rtdlightshadows)
980 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
982 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
984 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
986 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);
991 R_TimeReport("worldvis");
994 R_TimeReport("markentity");
996 R_Shadow_UpdateWorldLightSelection();
998 // don't let sound skip if going slow
999 if (r_refdef.extraupdate)
1002 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1003 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1005 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1006 R_TimeReport("worldsky");
1009 if (R_DrawBrushModelsSky())
1010 R_TimeReport("bmodelsky");
1012 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1013 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1015 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1016 R_TimeReport("world");
1019 // don't let sound skip if going slow
1020 if (r_refdef.extraupdate)
1023 GL_ShowTrisColor(0, 0.015, 0, 1);
1026 R_TimeReport("models");
1028 // don't let sound skip if going slow
1029 if (r_refdef.extraupdate)
1032 GL_ShowTrisColor(0, 0, 0.033, 1);
1033 R_ShadowVolumeLighting(false);
1034 R_TimeReport("rtlights");
1036 // don't let sound skip if going slow
1037 if (r_refdef.extraupdate)
1040 GL_ShowTrisColor(0.1, 0, 0, 1);
1042 R_DrawLightningBeams();
1043 R_TimeReport("lightning");
1046 R_TimeReport("particles");
1049 R_TimeReport("explosions");
1051 R_MeshQueue_RenderTransparent();
1052 R_TimeReport("drawtrans");
1055 R_TimeReport("coronas");
1057 R_DrawWorldCrosshair();
1058 R_TimeReport("crosshair");
1060 R_MeshQueue_Render();
1061 R_MeshQueue_EndScene();
1063 if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1065 R_ShadowVolumeLighting(true);
1066 R_TimeReport("visiblevolume");
1069 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1071 // don't let sound skip if going slow
1072 if (r_refdef.extraupdate)
1077 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1080 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1082 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1083 GL_DepthMask(false);
1085 R_Mesh_Matrix(&r_identitymatrix);
1087 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1088 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1089 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1090 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1091 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1092 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1093 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1094 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1095 R_FillColors(color, 8, cr, cg, cb, ca);
1098 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1100 VectorSubtract(v, r_vieworigin, diff);
1101 f2 = exp(fogdensity/DotProduct(diff, diff));
1103 c[0] = c[0] * f1 + fogcolor[0] * f2;
1104 c[1] = c[1] * f1 + fogcolor[1] * f2;
1105 c[2] = c[2] * f1 + fogcolor[2] * f2;
1108 memset(&m, 0, sizeof(m));
1109 m.pointer_vertex = vertex3f;
1110 m.pointer_color = color;
1116 int nomodelelements[24] =
1128 float nomodelvertex3f[6*3] =
1138 float nomodelcolor4f[6*4] =
1140 0.0f, 0.0f, 0.5f, 1.0f,
1141 0.0f, 0.0f, 0.5f, 1.0f,
1142 0.0f, 0.5f, 0.0f, 1.0f,
1143 0.0f, 0.5f, 0.0f, 1.0f,
1144 0.5f, 0.0f, 0.0f, 1.0f,
1145 0.5f, 0.0f, 0.0f, 1.0f
1148 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1150 const entity_render_t *ent = (entity_render_t *)calldata1;
1152 float f1, f2, *c, diff[3];
1155 R_Mesh_Matrix(&ent->matrix);
1157 memset(&m, 0, sizeof(m));
1158 m.pointer_vertex = nomodelvertex3f;
1160 if (ent->flags & EF_ADDITIVE)
1162 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1163 GL_DepthMask(false);
1165 else if (ent->alpha < 1)
1167 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1168 GL_DepthMask(false);
1172 GL_BlendFunc(GL_ONE, GL_ZERO);
1175 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1178 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1179 m.pointer_color = color4f;
1180 VectorSubtract(ent->origin, r_vieworigin, diff);
1181 f2 = exp(fogdensity/DotProduct(diff, diff));
1183 for (i = 0, c = color4f;i < 6;i++, c += 4)
1185 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1186 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1187 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1191 else if (ent->alpha != 1)
1193 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1194 m.pointer_color = color4f;
1195 for (i = 0, c = color4f;i < 6;i++, c += 4)
1199 m.pointer_color = nomodelcolor4f;
1201 R_Mesh_Draw(0, 6, 8, nomodelelements);
1204 void R_DrawNoModel(entity_render_t *ent)
1206 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1207 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1209 // R_DrawNoModelCallback(ent, 0);
1212 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1214 vec3_t right1, right2, diff, normal;
1216 VectorSubtract (org2, org1, normal);
1218 // calculate 'right' vector for start
1219 VectorSubtract (r_vieworigin, org1, diff);
1220 CrossProduct (normal, diff, right1);
1221 VectorNormalize (right1);
1223 // calculate 'right' vector for end
1224 VectorSubtract (r_vieworigin, org2, diff);
1225 CrossProduct (normal, diff, right2);
1226 VectorNormalize (right2);
1228 vert[ 0] = org1[0] + width * right1[0];
1229 vert[ 1] = org1[1] + width * right1[1];
1230 vert[ 2] = org1[2] + width * right1[2];
1231 vert[ 3] = org1[0] - width * right1[0];
1232 vert[ 4] = org1[1] - width * right1[1];
1233 vert[ 5] = org1[2] - width * right1[2];
1234 vert[ 6] = org2[0] - width * right2[0];
1235 vert[ 7] = org2[1] - width * right2[1];
1236 vert[ 8] = org2[2] - width * right2[2];
1237 vert[ 9] = org2[0] + width * right2[0];
1238 vert[10] = org2[1] + width * right2[1];
1239 vert[11] = org2[2] + width * right2[2];
1242 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1244 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)
1251 VectorSubtract(origin, r_vieworigin, diff);
1252 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1255 R_Mesh_Matrix(&r_identitymatrix);
1256 GL_BlendFunc(blendfunc1, blendfunc2);
1257 GL_DepthMask(false);
1258 GL_DepthTest(!depthdisable);
1260 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1261 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1262 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1263 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1264 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1265 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1266 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1267 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1268 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1269 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1270 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1271 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1273 memset(&m, 0, sizeof(m));
1274 m.tex[0] = R_GetTexture(texture);
1275 m.pointer_texcoord[0] = spritetexcoord2f;
1276 m.pointer_vertex = varray_vertex3f;
1278 GL_Color(cr, cg, cb, ca);
1279 R_Mesh_Draw(0, 4, 2, polygonelements);
1282 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1286 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1287 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1289 if (i == mesh->numvertices)
1291 if (mesh->numvertices < mesh->maxvertices)
1293 VectorCopy(v, vertex3f);
1294 mesh->numvertices++;
1296 return mesh->numvertices;
1302 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1306 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1307 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1308 e = mesh->element3i + mesh->numtriangles * 3;
1309 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1311 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1312 if (mesh->numtriangles < mesh->maxtriangles)
1317 mesh->numtriangles++;
1319 element[1] = element[2];
1323 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1325 int planenum, planenum2;
1328 mplane_t *plane, *plane2;
1329 float temppoints[2][256*3];
1330 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1334 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1335 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1337 if (planenum2 == planenum)
1339 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);
1342 if (tempnumpoints < 3)
1344 // generate elements forming a triangle fan for this polygon
1345 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1349 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)
1351 texturelayer_t *layer;
1352 layer = t->currentlayers + t->currentnumlayers++;
1354 layer->depthmask = depthmask;
1355 layer->blendfunc1 = blendfunc1;
1356 layer->blendfunc2 = blendfunc2;
1357 layer->texture = texture;
1358 layer->texmatrix = *matrix;
1359 layer->color[0] = r;
1360 layer->color[1] = g;
1361 layer->color[2] = b;
1362 layer->color[3] = a;
1365 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1367 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1368 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1372 texture_t *texture = t;
1373 model_t *model = ent->model;
1374 int s = ent->skinnum;
1375 if ((unsigned int)s >= (unsigned int)model->numskins)
1377 if (model->skinscenes)
1379 if (model->skinscenes[s].framecount > 1)
1380 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1382 s = model->skinscenes[s].firstframe;
1385 t = t + s * model->num_surfaces;
1387 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];
1388 texture->currentframe = t;
1391 t->currentmaterialflags = t->basematerialflags;
1392 currentalpha = ent->alpha;
1393 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1394 currentalpha *= r_wateralpha.value;
1395 if (!(ent->flags & RENDER_LIGHT))
1396 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1397 if (ent->effects & EF_ADDITIVE)
1398 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1399 else if (currentalpha < 1)
1400 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1401 if (ent->effects & EF_NODEPTHTEST)
1402 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1403 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1404 t->currenttexmatrix = r_waterscrollmatrix;
1406 t->currenttexmatrix = r_identitymatrix;
1407 t->currentnumlayers = 0;
1408 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1410 if (gl_lightmaps.integer)
1411 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1412 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1414 // transparent sky would be ridiculous
1415 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1416 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1420 int blendfunc1, blendfunc2, depthmask;
1421 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1423 blendfunc1 = GL_SRC_ALPHA;
1424 blendfunc2 = GL_ONE;
1427 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1429 blendfunc1 = GL_SRC_ALPHA;
1430 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1435 blendfunc1 = GL_ONE;
1436 blendfunc2 = GL_ZERO;
1439 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1441 rtexture_t *currentbasetexture;
1443 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1444 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1445 currentbasetexture = (ent->colormap < 0 && t->skin.merged) ? t->skin.merged : t->skin.base;
1446 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1448 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], currentalpha);
1449 if (ent->colormap >= 0 && t->skin.pants)
1450 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);
1451 if (ent->colormap >= 0 && t->skin.shirt)
1452 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);
1458 // q3bsp has no lightmap updates, so the lightstylevalue that
1459 // would normally be baked into the lightmaptexture must be
1460 // applied to the color
1461 if (ent->model->type == mod_brushq3)
1462 colorscale *= d_lightstylevalue[0] * (1.0f / 256.0f);
1463 // transparent and fullbright are not affected by r_lightmapintensity
1464 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1465 colorscale *= r_lightmapintensity;
1466 if (r_textureunits.integer >= 2 && gl_combine.integer)
1467 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);
1468 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1469 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);
1471 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);
1472 if (r_ambient.value >= (1.0f/64.0f))
1473 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);
1474 if (ent->colormap >= 0 && t->skin.pants)
1476 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);
1477 if (r_ambient.value >= (1.0f/64.0f))
1478 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);
1480 if (ent->colormap >= 0 && t->skin.shirt)
1482 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);
1483 if (r_ambient.value >= (1.0f/64.0f))
1484 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);
1487 if (t->skin.glow != NULL)
1488 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, currentalpha);
1489 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1491 // if this is opaque use alpha blend which will darken the earlier
1494 // if this is an alpha blended material, all the earlier passes
1495 // were darkened by fog already, so we only need to add the fog
1496 // color ontop through the fog mask texture
1498 // if this is an additive blended material, all the earlier passes
1499 // were darkened by fog already, and we should not add fog color
1500 // (because the background was not darkened, there is no fog color
1501 // that was lost behind it).
1502 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);
1509 void R_UpdateAllTextureInfo(entity_render_t *ent)
1513 for (i = 0;i < ent->model->num_textures;i++)
1514 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1517 float *rsurface_vertex3f;
1518 float *rsurface_svector3f;
1519 float *rsurface_tvector3f;
1520 float *rsurface_normal3f;
1521 float *rsurface_lightmapcolor4f;
1523 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1526 float center[3], forward[3], right[3], up[3], v[4][3];
1527 matrix4x4_t matrix1, imatrix1;
1528 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1530 rsurface_vertex3f = varray_vertex3f;
1531 rsurface_svector3f = NULL;
1532 rsurface_tvector3f = NULL;
1533 rsurface_normal3f = NULL;
1534 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1538 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1539 rsurface_svector3f = surface->groupmesh->data_svector3f;
1540 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1541 rsurface_normal3f = surface->groupmesh->data_normal3f;
1543 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1545 if (!rsurface_svector3f)
1547 rsurface_svector3f = varray_svector3f;
1548 rsurface_tvector3f = varray_tvector3f;
1549 rsurface_normal3f = varray_normal3f;
1550 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);
1552 // a single autosprite surface can contain multiple sprites...
1553 VectorClear(forward);
1555 VectorSet(up, 0, 0, 1);
1556 for (j = 0;j < surface->num_vertices - 3;j += 4)
1558 VectorClear(center);
1559 for (i = 0;i < 4;i++)
1560 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1561 VectorScale(center, 0.25f, center);
1562 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1563 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);
1564 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1565 for (i = 0;i < 4;i++)
1566 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1567 forward[0] = modelorg[0] - center[0];
1568 forward[1] = modelorg[1] - center[1];
1569 VectorNormalize(forward);
1570 right[0] = forward[1];
1571 right[1] = -forward[0];
1572 for (i = 0;i < 4;i++)
1573 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1575 rsurface_vertex3f = varray_vertex3f;
1576 rsurface_svector3f = NULL;
1577 rsurface_tvector3f = NULL;
1578 rsurface_normal3f = NULL;
1580 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1582 if (!rsurface_svector3f)
1584 rsurface_svector3f = varray_svector3f;
1585 rsurface_tvector3f = varray_tvector3f;
1586 rsurface_normal3f = varray_normal3f;
1587 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);
1589 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1590 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1591 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1592 // a single autosprite surface can contain multiple sprites...
1593 for (j = 0;j < surface->num_vertices - 3;j += 4)
1595 VectorClear(center);
1596 for (i = 0;i < 4;i++)
1597 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1598 VectorScale(center, 0.25f, center);
1599 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1600 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);
1601 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1602 for (i = 0;i < 4;i++)
1603 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1604 for (i = 0;i < 4;i++)
1605 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1607 rsurface_vertex3f = varray_vertex3f;
1608 rsurface_svector3f = NULL;
1609 rsurface_tvector3f = NULL;
1610 rsurface_normal3f = NULL;
1612 R_Mesh_VertexPointer(rsurface_vertex3f);
1615 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)
1624 vec4_t ambientcolor4f;
1625 vec3_t diffusecolor;
1626 vec3_t diffusenormal;
1627 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1629 rsurface_lightmapcolor4f = varray_color4f;
1630 if (rsurface_normal3f == NULL)
1632 rsurface_normal3f = varray_normal3f;
1633 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);
1635 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);
1644 r = ambientcolor4f[0];
1645 g = ambientcolor4f[1];
1646 b = ambientcolor4f[2];
1647 a = ambientcolor4f[3];
1648 rsurface_lightmapcolor4f = NULL;
1651 else if (lightmode >= 1)
1653 if (surface->lightmapinfo)
1655 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1657 const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1660 float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1661 VectorScale(lm, scale, c);
1662 if (surface->lightmapinfo->styles[1] != 255)
1664 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1666 scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1667 VectorMA(c, scale, lm, c);
1668 if (surface->lightmapinfo->styles[2] != 255)
1671 scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1672 VectorMA(c, scale, lm, c);
1673 if (surface->lightmapinfo->styles[3] != 255)
1676 scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1677 VectorMA(c, scale, lm, c);
1685 rsurface_lightmapcolor4f = varray_color4f;
1688 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1691 rsurface_lightmapcolor4f = NULL;
1694 if (rsurface_lightmapcolor4f)
1696 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)
1698 VectorSubtract(v, modelorg, diff);
1699 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1708 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)
1710 VectorSubtract(v, modelorg, diff);
1711 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1718 rsurface_lightmapcolor4f = varray_color4f;
1720 if (applycolor && rsurface_lightmapcolor4f)
1722 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)
1729 rsurface_lightmapcolor4f = varray_color4f;
1731 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1732 GL_Color(r, g, b, a);
1736 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1738 int texturesurfaceindex;
1740 const msurface_t *surface;
1741 qboolean applycolor;
1743 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1745 renderstats.entities_surfaces += texturenumsurfaces;
1746 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1747 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1748 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1749 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1750 qglDisable(GL_CULL_FACE);
1751 if (texture->currentnumlayers)
1754 texturelayer_t *layer;
1755 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1758 int layertexrgbscale;
1759 GL_DepthMask(layer->depthmask);
1760 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1761 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1763 layertexrgbscale = 4;
1764 VectorScale(layer->color, 0.25f, layercolor);
1766 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
1768 layertexrgbscale = 2;
1769 VectorScale(layer->color, 0.5f, layercolor);
1773 layertexrgbscale = 1;
1774 VectorScale(layer->color, 1.0f, layercolor);
1776 layercolor[3] = layer->color[3];
1777 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1778 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
1779 switch (layer->type)
1781 case TEXTURELAYERTYPE_SKY:
1784 skyrendernow = false;
1785 if (skyrendermasked)
1788 // restore entity matrix and GL_Color
1789 R_Mesh_Matrix(&ent->matrix);
1790 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1793 // LordHavoc: HalfLife maps have freaky skypolys...
1794 //if (!ent->model->brush.ishlbsp)
1796 if (skyrendermasked)
1798 // depth-only (masking)
1799 GL_ColorMask(0,0,0,0);
1800 // just to make sure that braindead drivers don't draw anything
1801 // despite that colormask...
1802 GL_BlendFunc(GL_ZERO, GL_ONE);
1807 GL_BlendFunc(GL_ONE, GL_ZERO);
1809 memset(&m, 0, sizeof(m));
1811 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1813 surface = texturesurfacelist[texturesurfaceindex];
1814 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1815 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1816 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1817 GL_LockArrays(0, 0);
1819 if (skyrendermasked)
1820 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1823 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
1824 memset(&m, 0, sizeof(m));
1825 m.tex[1] = R_GetTexture(layer->texture);
1826 m.texmatrix[1] = layer->texmatrix;
1827 m.texrgbscale[1] = layertexrgbscale;
1828 m.pointer_color = varray_color4f;
1830 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1832 surface = texturesurfacelist[texturesurfaceindex];
1833 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1834 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1835 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1838 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1839 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1841 else if (surface->lightmaptexture)
1843 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1844 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1848 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1849 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1851 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1852 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1853 GL_LockArrays(0, 0);
1856 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
1857 memset(&m, 0, sizeof(m));
1858 m.tex[0] = R_GetTexture(layer->texture);
1859 m.texmatrix[0] = layer->texmatrix;
1860 m.pointer_color = varray_color4f;
1861 m.texrgbscale[0] = layertexrgbscale;
1863 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1865 surface = texturesurfacelist[texturesurfaceindex];
1866 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1867 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1870 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1871 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
1873 else if (surface->lightmaptexture)
1875 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1876 R_Mesh_ColorPointer(NULL);
1880 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1881 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
1883 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1884 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1885 GL_LockArrays(0, 0);
1887 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1888 memset(&m, 0, sizeof(m));
1889 m.tex[0] = R_GetTexture(layer->texture);
1890 m.texmatrix[0] = layer->texmatrix;
1891 m.pointer_color = varray_color4f;
1892 m.texrgbscale[0] = layertexrgbscale;
1894 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1896 surface = texturesurfacelist[texturesurfaceindex];
1897 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1898 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1899 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1900 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1901 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1902 GL_LockArrays(0, 0);
1905 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
1906 memset(&m, 0, sizeof(m));
1907 m.tex[0] = R_GetTexture(layer->texture);
1908 m.texmatrix[0] = layer->texmatrix;
1909 m.texrgbscale[0] = layertexrgbscale;
1910 m.pointer_color = varray_color4f;
1912 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1914 surface = texturesurfacelist[texturesurfaceindex];
1915 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1916 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1917 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1918 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1919 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1920 GL_LockArrays(0, 0);
1923 case TEXTURELAYERTYPE_TEXTURE:
1924 memset(&m, 0, sizeof(m));
1925 m.tex[0] = R_GetTexture(layer->texture);
1926 m.texmatrix[0] = layer->texmatrix;
1927 m.pointer_color = varray_color4f;
1928 m.texrgbscale[0] = layertexrgbscale;
1930 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1932 surface = texturesurfacelist[texturesurfaceindex];
1933 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1934 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1935 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1936 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1937 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1938 GL_LockArrays(0, 0);
1941 case TEXTURELAYERTYPE_FOG:
1942 memset(&m, 0, sizeof(m));
1945 m.tex[0] = R_GetTexture(layer->texture);
1946 m.texmatrix[0] = layer->texmatrix;
1949 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1954 surface = texturesurfacelist[texturesurfaceindex];
1955 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1957 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1958 R_Mesh_ColorPointer(varray_color4f);
1959 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)
1961 VectorSubtract(v, modelorg, diff);
1962 f = exp(fogdensity/DotProduct(diff, diff));
1963 c[0] = layercolor[0];
1964 c[1] = layercolor[1];
1965 c[2] = layercolor[2];
1966 c[3] = f * layercolor[3];
1968 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1969 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1970 GL_LockArrays(0, 0);
1974 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
1976 // if trying to do overbright on first pass of an opaque surface
1977 // when combine is not supported, brighten as a post process
1978 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
1981 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1982 GL_Color(1, 1, 1, 1);
1983 memset(&m, 0, sizeof(m));
1985 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1987 surface = texturesurfacelist[texturesurfaceindex];
1988 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1989 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1990 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
1991 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1992 GL_LockArrays(0, 0);
1997 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1998 qglEnable(GL_CULL_FACE);
2001 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2003 const entity_render_t *ent = (entity_render_t *)calldata1;
2004 const msurface_t *surface = ent->model->data_surfaces + calldata2;
2008 texture = surface->texture;
2009 if (texture->basematerialflags & MATERIALFLAG_SKY)
2010 return; // transparent sky is too difficult
2011 R_UpdateTextureInfo(ent, texture);
2013 R_Mesh_Matrix(&ent->matrix);
2014 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2015 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2018 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2020 int texturesurfaceindex;
2021 const msurface_t *surface;
2022 vec3_t tempcenter, center;
2023 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2025 // drawing sky transparently would be too difficult
2026 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2028 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2030 surface = texturesurfacelist[texturesurfaceindex];
2031 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2032 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2033 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2034 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2035 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2040 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2043 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2044 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2046 int i, j, f, flagsmask;
2047 int counttriangles = 0;
2048 msurface_t *surface, **surfacechain;
2049 texture_t *t, *texture;
2050 model_t *model = ent->model;
2052 const int maxsurfacelist = 1024;
2053 int numsurfacelist = 0;
2054 const msurface_t *surfacelist[1024];
2057 R_Mesh_Matrix(&ent->matrix);
2058 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2060 // update light styles
2061 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2063 for (i = 0;i < model->brushq1.light_styles;i++)
2065 if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
2067 model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
2068 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2069 for (;(surface = *surfacechain);surfacechain++)
2070 surface->cached_dlight = true;
2075 R_UpdateAllTextureInfo(ent);
2076 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2081 if (ent == r_refdef.worldentity)
2083 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2085 if (!r_worldsurfacevisible[j])
2087 if (t != surface->texture)
2091 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2094 t = surface->texture;
2095 texture = t->currentframe;
2096 f = texture->currentmaterialflags & flagsmask;
2098 if (f && surface->num_triangles)
2100 // if lightmap parameters changed, rebuild lightmap texture
2101 if (surface->cached_dlight && surface->lightmapinfo->samples)
2102 R_BuildLightMap(ent, surface);
2103 // add face to draw list
2104 surfacelist[numsurfacelist++] = surface;
2105 counttriangles += surface->num_triangles;
2106 if (numsurfacelist >= maxsurfacelist)
2108 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2116 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2118 if (t != surface->texture)
2122 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2125 t = surface->texture;
2126 texture = t->currentframe;
2127 f = texture->currentmaterialflags & flagsmask;
2129 if (f && surface->num_triangles)
2131 // if lightmap parameters changed, rebuild lightmap texture
2132 if (surface->cached_dlight && surface->lightmapinfo->samples)
2133 R_BuildLightMap(ent, surface);
2134 // add face to draw list
2135 surfacelist[numsurfacelist++] = surface;
2136 counttriangles += surface->num_triangles;
2137 if (numsurfacelist >= maxsurfacelist)
2139 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2146 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2147 if (!r_showtrispass)
2148 renderstats.entities_triangles += counttriangles;