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 // some of the renderer still relies on origin...
586 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
587 // some of the renderer still relies on scale...
588 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
589 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)))
591 R_UpdateEntLights(ent);
592 ent->visframe = r_framecount;
598 // no worldmodel or it can't check visibility
599 for (i = 0;i < r_refdef.numentities;i++)
601 ent = r_refdef.entities[i];
602 // some of the renderer still relies on origin...
603 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
604 // some of the renderer still relies on scale...
605 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
606 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
608 R_UpdateEntLights(ent);
609 ent->visframe = r_framecount;
615 // only used if skyrendermasked, and normally returns false
616 int R_DrawBrushModelsSky (void)
619 entity_render_t *ent;
621 if (!r_drawentities.integer)
625 for (i = 0;i < r_refdef.numentities;i++)
627 ent = r_refdef.entities[i];
628 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
630 ent->model->DrawSky(ent);
637 void R_DrawNoModel(entity_render_t *ent);
638 void R_DrawModels(void)
641 entity_render_t *ent;
643 if (!r_drawentities.integer)
646 for (i = 0;i < r_refdef.numentities;i++)
648 ent = r_refdef.entities[i];
649 if (ent->visframe == r_framecount)
651 renderstats.entities++;
652 if (ent->model && ent->model->Draw != NULL)
653 ent->model->Draw(ent);
660 static void R_SetFrustum(void)
662 // break apart the view matrix into vectors for various purposes
663 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
664 VectorNegate(r_viewleft, r_viewright);
666 // LordHavoc: note to all quake engine coders, the special case for 90
667 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
670 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
671 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
672 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
673 PlaneClassify(&frustum[0]);
675 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
676 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
677 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
678 PlaneClassify(&frustum[1]);
680 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
681 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
682 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
683 PlaneClassify(&frustum[2]);
685 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
686 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
687 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
688 PlaneClassify(&frustum[3]);
691 VectorCopy(r_viewforward, frustum[4].normal);
692 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
693 PlaneClassify(&frustum[4]);
696 static void R_BlendView(void)
700 if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
703 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
706 R_Mesh_Matrix(&r_identitymatrix);
707 // vertex coordinates for a quad that covers the screen exactly
708 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
709 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
710 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
711 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
712 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)
714 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
715 float xoffset, yoffset, r;
717 // set the (poorly named) screenwidth and screenheight variables to
718 // a power of 2 at least as large as the screen, these will define the
719 // size of the texture to allocate
720 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
721 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
722 // allocate textures as needed
723 if (!r_bloom_texture_screen)
724 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
725 if (!r_bloom_texture_bloom)
726 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
727 // set bloomwidth and bloomheight to the bloom resolution that will be
728 // used (often less than the screen resolution for faster rendering)
729 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
730 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
731 // set up a texcoord array for the full resolution screen image
732 // (we have to keep this around to copy back during final render)
733 varray_texcoord2f[0][0] = 0;
734 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
735 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
736 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
737 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
738 varray_texcoord2f[0][5] = 0;
739 varray_texcoord2f[0][6] = 0;
740 varray_texcoord2f[0][7] = 0;
741 // set up a texcoord array for the reduced resolution bloom image
742 // (which will be additive blended over the screen image)
743 varray_texcoord2f[1][0] = 0;
744 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
745 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
746 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
747 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
748 varray_texcoord2f[1][5] = 0;
749 varray_texcoord2f[1][6] = 0;
750 varray_texcoord2f[1][7] = 0;
751 memset(&m, 0, sizeof(m));
752 m.pointer_vertex = varray_vertex3f;
753 m.pointer_texcoord[0] = varray_texcoord2f[0];
754 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
756 // copy view into the full resolution screen image texture
758 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
759 renderstats.bloom_copypixels += r_view_width * r_view_height;
760 // now scale it down to the bloom size and raise to a power of itself
761 // to darken it (this leaves the really bright stuff bright, and
762 // everything else becomes very dark)
763 // TODO: optimize with multitexture or GLSL
764 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
765 GL_BlendFunc(GL_ONE, GL_ZERO);
766 GL_Color(1, 1, 1, 1);
767 R_Mesh_Draw(0, 4, 2, polygonelements);
768 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
769 // render multiple times with a multiply blendfunc to raise to a power
770 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
771 for (x = 1;x < r_bloom_power.integer;x++)
773 R_Mesh_Draw(0, 4, 2, polygonelements);
774 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
776 // we now have a darkened bloom image in the framebuffer, copy it into
777 // the bloom image texture for more processing
778 memset(&m, 0, sizeof(m));
779 m.pointer_vertex = varray_vertex3f;
780 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
781 m.pointer_texcoord[0] = varray_texcoord2f[2];
784 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
785 renderstats.bloom_copypixels += bloomwidth * bloomheight;
786 // blend on at multiple vertical offsets to achieve a vertical blur
787 // TODO: do offset blends using GLSL
788 range = r_bloom_blur.integer * bloomwidth / 320;
789 GL_BlendFunc(GL_ONE, GL_ZERO);
790 for (x = -range;x <= range;x++)
792 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
793 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
794 // compute a texcoord array with the specified x and y offset
795 varray_texcoord2f[2][0] = xoffset+0;
796 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
797 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
798 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
799 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
800 varray_texcoord2f[2][5] = yoffset+0;
801 varray_texcoord2f[2][6] = xoffset+0;
802 varray_texcoord2f[2][7] = yoffset+0;
803 // this r value looks like a 'dot' particle, fading sharply to
804 // black at the edges
805 // (probably not realistic but looks good enough)
806 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
809 GL_Color(r, r, r, 1);
810 R_Mesh_Draw(0, 4, 2, polygonelements);
811 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
812 GL_BlendFunc(GL_ONE, GL_ONE);
814 // copy the vertically blurred bloom view to a texture
816 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
817 renderstats.bloom_copypixels += bloomwidth * bloomheight;
818 // blend the vertically blurred image at multiple offsets horizontally
819 // to finish the blur effect
820 // TODO: do offset blends using GLSL
821 range = r_bloom_blur.integer * bloomwidth / 320;
822 GL_BlendFunc(GL_ONE, GL_ZERO);
823 for (x = -range;x <= range;x++)
825 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
826 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
827 // compute a texcoord array with the specified x and y offset
828 varray_texcoord2f[2][0] = xoffset+0;
829 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
830 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
831 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
832 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
833 varray_texcoord2f[2][5] = yoffset+0;
834 varray_texcoord2f[2][6] = xoffset+0;
835 varray_texcoord2f[2][7] = yoffset+0;
836 // this r value looks like a 'dot' particle, fading sharply to
837 // black at the edges
838 // (probably not realistic but looks good enough)
839 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
842 GL_Color(r, r, r, 1);
843 R_Mesh_Draw(0, 4, 2, polygonelements);
844 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
845 GL_BlendFunc(GL_ONE, GL_ONE);
847 // copy the blurred bloom view to a texture
849 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
850 renderstats.bloom_copypixels += bloomwidth * bloomheight;
851 // go back to full view area
852 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
853 // put the original screen image back in place and blend the bloom
855 memset(&m, 0, sizeof(m));
856 m.pointer_vertex = varray_vertex3f;
857 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
858 m.pointer_texcoord[0] = varray_texcoord2f[0];
860 dobloomblend = false;
862 // do both in one pass if possible
863 if (r_textureunits.integer >= 2 && gl_combine.integer)
865 dobloomblend = false;
866 m.texcombinergb[1] = GL_ADD;
867 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
868 m.pointer_texcoord[1] = varray_texcoord2f[1];
874 GL_BlendFunc(GL_ONE, GL_ZERO);
876 R_Mesh_Draw(0, 4, 2, polygonelements);
877 renderstats.bloom_drawpixels += r_view_width * r_view_height;
878 // now blend on the bloom texture if multipass
881 memset(&m, 0, sizeof(m));
882 m.pointer_vertex = varray_vertex3f;
883 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
884 m.pointer_texcoord[0] = varray_texcoord2f[1];
886 GL_BlendFunc(GL_ONE, GL_ONE);
888 R_Mesh_Draw(0, 4, 2, polygonelements);
889 renderstats.bloom_drawpixels += r_view_width * r_view_height;
892 if (r_refdef.viewblend[3] >= 0.01f)
894 // apply a color tint to the whole view
895 memset(&m, 0, sizeof(m));
896 m.pointer_vertex = varray_vertex3f;
898 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
899 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
900 R_Mesh_Draw(0, 4, 2, polygonelements);
904 void R_RenderScene(void);
906 matrix4x4_t r_waterscrollmatrix;
913 void R_RenderView(void)
915 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
916 return; //Host_Error ("R_RenderView: NULL worldmodel");
918 r_view_width = bound(0, r_refdef.width, vid.width);
919 r_view_height = bound(0, r_refdef.height, vid.height);
921 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
922 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
924 r_view_fov_x = bound(1, r_refdef.fov_x, 170);
925 r_view_fov_y = bound(1, r_refdef.fov_y, 170);
926 r_view_matrix = r_refdef.viewentitymatrix;
927 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
928 r_rtworld = r_shadow_realtime_world.integer;
929 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
930 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
931 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
932 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
934 // GL is weird because it's bottom to top, r_view_y is top to bottom
935 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
936 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
937 GL_ScissorTest(true);
943 R_TimeReport("setup");
945 qglDepthFunc(GL_LEQUAL);
946 qglPolygonOffset(0, 0);
947 qglEnable(GL_POLYGON_OFFSET_FILL);
951 qglPolygonOffset(0, 0);
952 qglDisable(GL_POLYGON_OFFSET_FILL);
955 R_TimeReport("blendview");
957 GL_Scissor(0, 0, vid.width, vid.height);
958 GL_ScissorTest(false);
961 extern void R_DrawLightningBeams (void);
962 void R_RenderScene(void)
964 // don't let sound skip if going slow
965 if (r_refdef.extraupdate)
970 R_MeshQueue_BeginScene();
972 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
976 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
977 if (r_rtworldshadows || r_rtdlightshadows)
978 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
980 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
982 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
984 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);
989 R_TimeReport("worldvis");
992 R_TimeReport("markentity");
994 R_Shadow_UpdateWorldLightSelection();
996 // don't let sound skip if going slow
997 if (r_refdef.extraupdate)
1000 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1001 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1003 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1004 R_TimeReport("worldsky");
1007 if (R_DrawBrushModelsSky())
1008 R_TimeReport("bmodelsky");
1010 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1011 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1013 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1014 R_TimeReport("world");
1017 // don't let sound skip if going slow
1018 if (r_refdef.extraupdate)
1021 GL_ShowTrisColor(0, 0.015, 0, 1);
1024 R_TimeReport("models");
1026 // don't let sound skip if going slow
1027 if (r_refdef.extraupdate)
1030 GL_ShowTrisColor(0, 0, 0.033, 1);
1031 R_ShadowVolumeLighting(false);
1032 R_TimeReport("rtlights");
1034 // don't let sound skip if going slow
1035 if (r_refdef.extraupdate)
1038 GL_ShowTrisColor(0.1, 0, 0, 1);
1040 R_DrawLightningBeams();
1041 R_TimeReport("lightning");
1044 R_TimeReport("particles");
1047 R_TimeReport("explosions");
1049 R_MeshQueue_RenderTransparent();
1050 R_TimeReport("drawtrans");
1053 R_TimeReport("coronas");
1055 R_DrawWorldCrosshair();
1056 R_TimeReport("crosshair");
1058 R_MeshQueue_Render();
1059 R_MeshQueue_EndScene();
1061 if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1063 R_ShadowVolumeLighting(true);
1064 R_TimeReport("visiblevolume");
1067 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1069 // don't let sound skip if going slow
1070 if (r_refdef.extraupdate)
1075 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1078 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1080 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1081 GL_DepthMask(false);
1083 R_Mesh_Matrix(&r_identitymatrix);
1085 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1086 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1087 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1088 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1089 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1090 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1091 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1092 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1093 R_FillColors(color, 8, cr, cg, cb, ca);
1096 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1098 VectorSubtract(v, r_vieworigin, diff);
1099 f2 = exp(fogdensity/DotProduct(diff, diff));
1101 c[0] = c[0] * f1 + fogcolor[0] * f2;
1102 c[1] = c[1] * f1 + fogcolor[1] * f2;
1103 c[2] = c[2] * f1 + fogcolor[2] * f2;
1106 memset(&m, 0, sizeof(m));
1107 m.pointer_vertex = vertex3f;
1108 m.pointer_color = color;
1114 int nomodelelements[24] =
1126 float nomodelvertex3f[6*3] =
1136 float nomodelcolor4f[6*4] =
1138 0.0f, 0.0f, 0.5f, 1.0f,
1139 0.0f, 0.0f, 0.5f, 1.0f,
1140 0.0f, 0.5f, 0.0f, 1.0f,
1141 0.0f, 0.5f, 0.0f, 1.0f,
1142 0.5f, 0.0f, 0.0f, 1.0f,
1143 0.5f, 0.0f, 0.0f, 1.0f
1146 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1148 const entity_render_t *ent = (entity_render_t *)calldata1;
1150 float f1, f2, *c, diff[3];
1153 R_Mesh_Matrix(&ent->matrix);
1155 memset(&m, 0, sizeof(m));
1156 m.pointer_vertex = nomodelvertex3f;
1158 if (ent->flags & EF_ADDITIVE)
1160 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1161 GL_DepthMask(false);
1163 else if (ent->alpha < 1)
1165 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1166 GL_DepthMask(false);
1170 GL_BlendFunc(GL_ONE, GL_ZERO);
1173 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1176 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1177 m.pointer_color = color4f;
1178 VectorSubtract(ent->origin, r_vieworigin, diff);
1179 f2 = exp(fogdensity/DotProduct(diff, diff));
1181 for (i = 0, c = color4f;i < 6;i++, c += 4)
1183 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1184 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1185 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1189 else if (ent->alpha != 1)
1191 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1192 m.pointer_color = color4f;
1193 for (i = 0, c = color4f;i < 6;i++, c += 4)
1197 m.pointer_color = nomodelcolor4f;
1199 R_Mesh_Draw(0, 6, 8, nomodelelements);
1202 void R_DrawNoModel(entity_render_t *ent)
1204 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1205 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1207 // R_DrawNoModelCallback(ent, 0);
1210 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1212 vec3_t right1, right2, diff, normal;
1214 VectorSubtract (org2, org1, normal);
1216 // calculate 'right' vector for start
1217 VectorSubtract (r_vieworigin, org1, diff);
1218 CrossProduct (normal, diff, right1);
1219 VectorNormalize (right1);
1221 // calculate 'right' vector for end
1222 VectorSubtract (r_vieworigin, org2, diff);
1223 CrossProduct (normal, diff, right2);
1224 VectorNormalize (right2);
1226 vert[ 0] = org1[0] + width * right1[0];
1227 vert[ 1] = org1[1] + width * right1[1];
1228 vert[ 2] = org1[2] + width * right1[2];
1229 vert[ 3] = org1[0] - width * right1[0];
1230 vert[ 4] = org1[1] - width * right1[1];
1231 vert[ 5] = org1[2] - width * right1[2];
1232 vert[ 6] = org2[0] - width * right2[0];
1233 vert[ 7] = org2[1] - width * right2[1];
1234 vert[ 8] = org2[2] - width * right2[2];
1235 vert[ 9] = org2[0] + width * right2[0];
1236 vert[10] = org2[1] + width * right2[1];
1237 vert[11] = org2[2] + width * right2[2];
1240 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1242 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)
1249 VectorSubtract(origin, r_vieworigin, diff);
1250 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1253 R_Mesh_Matrix(&r_identitymatrix);
1254 GL_BlendFunc(blendfunc1, blendfunc2);
1255 GL_DepthMask(false);
1256 GL_DepthTest(!depthdisable);
1258 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1259 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1260 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1261 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1262 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1263 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1264 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1265 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1266 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1267 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1268 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1269 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1271 memset(&m, 0, sizeof(m));
1272 m.tex[0] = R_GetTexture(texture);
1273 m.pointer_texcoord[0] = spritetexcoord2f;
1274 m.pointer_vertex = varray_vertex3f;
1276 GL_Color(cr, cg, cb, ca);
1277 R_Mesh_Draw(0, 4, 2, polygonelements);
1280 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1284 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1285 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1287 if (i == mesh->numvertices)
1289 if (mesh->numvertices < mesh->maxvertices)
1291 VectorCopy(v, vertex3f);
1292 mesh->numvertices++;
1294 return mesh->numvertices;
1300 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1304 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1305 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1306 e = mesh->element3i + mesh->numtriangles * 3;
1307 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1309 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1310 if (mesh->numtriangles < mesh->maxtriangles)
1315 mesh->numtriangles++;
1317 element[1] = element[2];
1321 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1323 int planenum, planenum2;
1326 mplane_t *plane, *plane2;
1327 float temppoints[2][256*3];
1328 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1332 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1333 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1335 if (planenum2 == planenum)
1337 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);
1340 if (tempnumpoints < 3)
1342 // generate elements forming a triangle fan for this polygon
1343 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1347 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)
1349 texturelayer_t *layer;
1350 layer = t->currentlayers + t->currentnumlayers++;
1352 layer->depthmask = depthmask;
1353 layer->blendfunc1 = blendfunc1;
1354 layer->blendfunc2 = blendfunc2;
1355 layer->texture = texture;
1356 layer->texmatrix = *matrix;
1357 layer->color[0] = r;
1358 layer->color[1] = g;
1359 layer->color[2] = b;
1360 layer->color[3] = a;
1363 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1365 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1366 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1370 texture_t *texture = t;
1371 model_t *model = ent->model;
1372 int s = ent->skinnum;
1373 if ((unsigned int)s >= (unsigned int)model->numskins)
1375 if (model->skinscenes)
1377 if (model->skinscenes[s].framecount > 1)
1378 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1380 s = model->skinscenes[s].firstframe;
1383 t = t + s * model->num_surfaces;
1385 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];
1386 texture->currentframe = t;
1389 t->currentmaterialflags = t->basematerialflags;
1390 currentalpha = ent->alpha;
1391 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1392 currentalpha *= r_wateralpha.value;
1393 if (!(ent->flags & RENDER_LIGHT))
1394 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1395 if (ent->effects & EF_ADDITIVE)
1396 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1397 else if (currentalpha < 1)
1398 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1399 if (ent->effects & EF_NODEPTHTEST)
1400 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1401 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1402 t->currenttexmatrix = r_waterscrollmatrix;
1404 t->currenttexmatrix = r_identitymatrix;
1405 t->currentnumlayers = 0;
1406 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1408 if (gl_lightmaps.integer)
1409 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1410 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1412 // transparent sky would be ridiculous
1413 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1414 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1418 int blendfunc1, blendfunc2, depthmask;
1419 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1421 blendfunc1 = GL_SRC_ALPHA;
1422 blendfunc2 = GL_ONE;
1425 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1427 blendfunc1 = GL_SRC_ALPHA;
1428 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1433 blendfunc1 = GL_ONE;
1434 blendfunc2 = GL_ZERO;
1437 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1439 rtexture_t *currentbasetexture;
1441 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1442 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1443 currentbasetexture = (ent->colormap < 0 && t->skin.merged) ? t->skin.merged : t->skin.base;
1444 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1446 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], currentalpha);
1447 if (ent->colormap >= 0 && t->skin.pants)
1448 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);
1449 if (ent->colormap >= 0 && t->skin.shirt)
1450 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);
1456 // q3bsp has no lightmap updates, so the lightstylevalue that
1457 // would normally be baked into the lightmaptexture must be
1458 // applied to the color
1459 if (ent->model->type == mod_brushq3)
1460 colorscale *= d_lightstylevalue[0] * (1.0f / 256.0f);
1461 // transparent and fullbright are not affected by r_lightmapintensity
1462 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1463 colorscale *= r_lightmapintensity;
1464 if (r_textureunits.integer >= 2 && gl_combine.integer)
1465 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);
1466 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1467 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);
1469 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);
1470 if (r_ambient.value >= (1.0f/64.0f))
1471 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);
1472 if (ent->colormap >= 0 && t->skin.pants)
1474 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);
1475 if (r_ambient.value >= (1.0f/64.0f))
1476 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);
1478 if (ent->colormap >= 0 && t->skin.shirt)
1480 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);
1481 if (r_ambient.value >= (1.0f/64.0f))
1482 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);
1485 if (t->skin.glow != NULL)
1486 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, currentalpha);
1487 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1489 // if this is opaque use alpha blend which will darken the earlier
1492 // if this is an alpha blended material, all the earlier passes
1493 // were darkened by fog already, so we only need to add the fog
1494 // color ontop through the fog mask texture
1496 // if this is an additive blended material, all the earlier passes
1497 // were darkened by fog already, and we should not add fog color
1498 // (because the background was not darkened, there is no fog color
1499 // that was lost behind it).
1500 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);
1507 void R_UpdateAllTextureInfo(entity_render_t *ent)
1511 for (i = 0;i < ent->model->num_textures;i++)
1512 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1515 float *rsurface_vertex3f;
1516 float *rsurface_svector3f;
1517 float *rsurface_tvector3f;
1518 float *rsurface_normal3f;
1519 float *rsurface_lightmapcolor4f;
1521 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1524 float center[3], forward[3], right[3], up[3], v[4][3];
1525 matrix4x4_t matrix1, imatrix1;
1526 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1528 rsurface_vertex3f = varray_vertex3f;
1529 rsurface_svector3f = NULL;
1530 rsurface_tvector3f = NULL;
1531 rsurface_normal3f = NULL;
1532 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1536 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1537 rsurface_svector3f = surface->groupmesh->data_svector3f;
1538 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1539 rsurface_normal3f = surface->groupmesh->data_normal3f;
1541 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1543 if (!rsurface_svector3f)
1545 rsurface_svector3f = varray_svector3f;
1546 rsurface_tvector3f = varray_tvector3f;
1547 rsurface_normal3f = varray_normal3f;
1548 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);
1550 // a single autosprite surface can contain multiple sprites...
1551 VectorClear(forward);
1553 VectorSet(up, 0, 0, 1);
1554 for (j = 0;j < surface->num_vertices - 3;j += 4)
1556 VectorClear(center);
1557 for (i = 0;i < 4;i++)
1558 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1559 VectorScale(center, 0.25f, center);
1560 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1561 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);
1562 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1563 for (i = 0;i < 4;i++)
1564 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1565 forward[0] = modelorg[0] - center[0];
1566 forward[1] = modelorg[1] - center[1];
1567 VectorNormalize(forward);
1568 right[0] = forward[1];
1569 right[1] = -forward[0];
1570 for (i = 0;i < 4;i++)
1571 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1573 rsurface_vertex3f = varray_vertex3f;
1574 rsurface_svector3f = NULL;
1575 rsurface_tvector3f = NULL;
1576 rsurface_normal3f = NULL;
1578 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1580 if (!rsurface_svector3f)
1582 rsurface_svector3f = varray_svector3f;
1583 rsurface_tvector3f = varray_tvector3f;
1584 rsurface_normal3f = varray_normal3f;
1585 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);
1587 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1588 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1589 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1590 // a single autosprite surface can contain multiple sprites...
1591 for (j = 0;j < surface->num_vertices - 3;j += 4)
1593 VectorClear(center);
1594 for (i = 0;i < 4;i++)
1595 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1596 VectorScale(center, 0.25f, center);
1597 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1598 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);
1599 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1600 for (i = 0;i < 4;i++)
1601 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1602 for (i = 0;i < 4;i++)
1603 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1605 rsurface_vertex3f = varray_vertex3f;
1606 rsurface_svector3f = NULL;
1607 rsurface_tvector3f = NULL;
1608 rsurface_normal3f = NULL;
1610 R_Mesh_VertexPointer(rsurface_vertex3f);
1613 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)
1622 vec4_t ambientcolor4f;
1623 vec3_t diffusecolor;
1624 vec3_t diffusenormal;
1625 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1627 rsurface_lightmapcolor4f = varray_color4f;
1628 if (rsurface_normal3f == NULL)
1630 rsurface_normal3f = varray_normal3f;
1631 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);
1633 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);
1642 r = ambientcolor4f[0];
1643 g = ambientcolor4f[1];
1644 b = ambientcolor4f[2];
1645 a = ambientcolor4f[3];
1646 rsurface_lightmapcolor4f = NULL;
1649 else if (lightmode >= 1)
1651 if (surface->lightmapinfo)
1653 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1655 const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1658 float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1659 VectorScale(lm, scale, c);
1660 if (surface->lightmapinfo->styles[1] != 255)
1662 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1664 scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1665 VectorMA(c, scale, lm, c);
1666 if (surface->lightmapinfo->styles[2] != 255)
1669 scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1670 VectorMA(c, scale, lm, c);
1671 if (surface->lightmapinfo->styles[3] != 255)
1674 scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1675 VectorMA(c, scale, lm, c);
1683 rsurface_lightmapcolor4f = varray_color4f;
1686 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1689 rsurface_lightmapcolor4f = NULL;
1692 if (rsurface_lightmapcolor4f)
1694 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)
1696 VectorSubtract(v, modelorg, diff);
1697 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1706 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)
1708 VectorSubtract(v, modelorg, diff);
1709 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1716 rsurface_lightmapcolor4f = varray_color4f;
1718 if (applycolor && rsurface_lightmapcolor4f)
1720 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)
1727 rsurface_lightmapcolor4f = varray_color4f;
1729 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1730 GL_Color(r, g, b, a);
1734 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1736 int texturesurfaceindex;
1738 const msurface_t *surface;
1739 qboolean applycolor;
1741 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1743 renderstats.entities_surfaces += texturenumsurfaces;
1744 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1745 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1746 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1747 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1748 qglDisable(GL_CULL_FACE);
1749 if (texture->currentnumlayers)
1752 texturelayer_t *layer;
1753 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1756 int layertexrgbscale;
1757 GL_DepthMask(layer->depthmask);
1758 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1759 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1761 layertexrgbscale = 4;
1762 VectorScale(layer->color, 0.25f, layercolor);
1764 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
1766 layertexrgbscale = 2;
1767 VectorScale(layer->color, 0.5f, layercolor);
1771 layertexrgbscale = 1;
1772 VectorScale(layer->color, 1.0f, layercolor);
1774 layercolor[3] = layer->color[3];
1775 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1776 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
1777 switch (layer->type)
1779 case TEXTURELAYERTYPE_SKY:
1782 skyrendernow = false;
1783 if (skyrendermasked)
1786 // restore entity matrix and GL_Color
1787 R_Mesh_Matrix(&ent->matrix);
1788 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1791 // LordHavoc: HalfLife maps have freaky skypolys...
1792 //if (!ent->model->brush.ishlbsp)
1794 if (skyrendermasked)
1796 // depth-only (masking)
1797 GL_ColorMask(0,0,0,0);
1798 // just to make sure that braindead drivers don't draw anything
1799 // despite that colormask...
1800 GL_BlendFunc(GL_ZERO, GL_ONE);
1805 GL_BlendFunc(GL_ONE, GL_ZERO);
1807 memset(&m, 0, sizeof(m));
1809 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1811 surface = texturesurfacelist[texturesurfaceindex];
1812 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1813 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1814 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1815 GL_LockArrays(0, 0);
1817 if (skyrendermasked)
1818 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1821 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
1822 memset(&m, 0, sizeof(m));
1823 m.tex[1] = R_GetTexture(layer->texture);
1824 m.texmatrix[1] = layer->texmatrix;
1825 m.texrgbscale[1] = layertexrgbscale;
1826 m.pointer_color = varray_color4f;
1828 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1830 surface = texturesurfacelist[texturesurfaceindex];
1831 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1832 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1833 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1836 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1837 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1839 else if (surface->lightmaptexture)
1841 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1842 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1846 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1847 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1849 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1850 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1851 GL_LockArrays(0, 0);
1854 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
1855 memset(&m, 0, sizeof(m));
1856 m.tex[0] = R_GetTexture(layer->texture);
1857 m.texmatrix[0] = layer->texmatrix;
1858 m.pointer_color = varray_color4f;
1859 m.texrgbscale[0] = layertexrgbscale;
1861 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1863 surface = texturesurfacelist[texturesurfaceindex];
1864 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1865 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1868 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1869 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
1871 else if (surface->lightmaptexture)
1873 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1874 R_Mesh_ColorPointer(NULL);
1878 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1879 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
1881 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1882 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1883 GL_LockArrays(0, 0);
1885 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1886 memset(&m, 0, sizeof(m));
1887 m.tex[0] = R_GetTexture(layer->texture);
1888 m.texmatrix[0] = layer->texmatrix;
1889 m.pointer_color = varray_color4f;
1890 m.texrgbscale[0] = layertexrgbscale;
1892 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1894 surface = texturesurfacelist[texturesurfaceindex];
1895 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1896 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1897 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1898 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1899 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1900 GL_LockArrays(0, 0);
1903 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
1904 memset(&m, 0, sizeof(m));
1905 m.tex[0] = R_GetTexture(layer->texture);
1906 m.texmatrix[0] = layer->texmatrix;
1907 m.texrgbscale[0] = layertexrgbscale;
1908 m.pointer_color = varray_color4f;
1910 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1912 surface = texturesurfacelist[texturesurfaceindex];
1913 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1914 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1915 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1916 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1917 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1918 GL_LockArrays(0, 0);
1921 case TEXTURELAYERTYPE_TEXTURE:
1922 memset(&m, 0, sizeof(m));
1923 m.tex[0] = R_GetTexture(layer->texture);
1924 m.texmatrix[0] = layer->texmatrix;
1925 m.pointer_color = varray_color4f;
1926 m.texrgbscale[0] = layertexrgbscale;
1928 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1930 surface = texturesurfacelist[texturesurfaceindex];
1931 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1932 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1933 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1934 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1935 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1936 GL_LockArrays(0, 0);
1939 case TEXTURELAYERTYPE_FOG:
1940 memset(&m, 0, sizeof(m));
1943 m.tex[0] = R_GetTexture(layer->texture);
1944 m.texmatrix[0] = layer->texmatrix;
1947 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1952 surface = texturesurfacelist[texturesurfaceindex];
1953 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1955 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1956 R_Mesh_ColorPointer(varray_color4f);
1957 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)
1959 VectorSubtract(v, modelorg, diff);
1960 f = exp(fogdensity/DotProduct(diff, diff));
1961 c[0] = layercolor[0];
1962 c[1] = layercolor[1];
1963 c[2] = layercolor[2];
1964 c[3] = f * layercolor[3];
1966 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1967 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1968 GL_LockArrays(0, 0);
1972 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
1974 // if trying to do overbright on first pass of an opaque surface
1975 // when combine is not supported, brighten as a post process
1976 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
1979 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1980 GL_Color(1, 1, 1, 1);
1981 memset(&m, 0, sizeof(m));
1983 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1985 surface = texturesurfacelist[texturesurfaceindex];
1986 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1987 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1988 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
1989 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1990 GL_LockArrays(0, 0);
1995 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1996 qglEnable(GL_CULL_FACE);
1999 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2001 const entity_render_t *ent = (entity_render_t *)calldata1;
2002 const msurface_t *surface = ent->model->data_surfaces + calldata2;
2006 texture = surface->texture;
2007 if (texture->basematerialflags & MATERIALFLAG_SKY)
2008 return; // transparent sky is too difficult
2009 R_UpdateTextureInfo(ent, texture);
2011 R_Mesh_Matrix(&ent->matrix);
2012 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2013 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2016 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2018 int texturesurfaceindex;
2019 const msurface_t *surface;
2020 vec3_t tempcenter, center;
2021 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2023 // drawing sky transparently would be too difficult
2024 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2026 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2028 surface = texturesurfacelist[texturesurfaceindex];
2029 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2030 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2031 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2032 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2033 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2038 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2041 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2042 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2044 int i, j, f, flagsmask;
2045 int counttriangles = 0;
2046 msurface_t *surface, **surfacechain;
2047 texture_t *t, *texture;
2048 model_t *model = ent->model;
2050 const int maxsurfacelist = 1024;
2051 int numsurfacelist = 0;
2052 const msurface_t *surfacelist[1024];
2055 R_Mesh_Matrix(&ent->matrix);
2056 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2058 // update light styles
2059 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2061 for (i = 0;i < model->brushq1.light_styles;i++)
2063 if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
2065 model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
2066 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2067 for (;(surface = *surfacechain);surfacechain++)
2068 surface->cached_dlight = true;
2073 R_UpdateAllTextureInfo(ent);
2074 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2079 if (ent == r_refdef.worldentity)
2081 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2083 if (!r_worldsurfacevisible[j])
2085 if (t != surface->texture)
2089 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2092 t = surface->texture;
2093 texture = t->currentframe;
2094 f = texture->currentmaterialflags & flagsmask;
2096 if (f && surface->num_triangles)
2098 // if lightmap parameters changed, rebuild lightmap texture
2099 if (surface->cached_dlight && surface->lightmapinfo->samples)
2100 R_BuildLightMap(ent, surface);
2101 // add face to draw list
2102 surfacelist[numsurfacelist++] = surface;
2103 counttriangles += surface->num_triangles;
2104 if (numsurfacelist >= maxsurfacelist)
2106 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2114 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2116 if (t != surface->texture)
2120 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2123 t = surface->texture;
2124 texture = t->currentframe;
2125 f = texture->currentmaterialflags & flagsmask;
2127 if (f && surface->num_triangles)
2129 // if lightmap parameters changed, rebuild lightmap texture
2130 if (surface->cached_dlight && surface->lightmapinfo->samples)
2131 R_BuildLightMap(ent, surface);
2132 // add face to draw list
2133 surfacelist[numsurfacelist++] = surface;
2134 counttriangles += surface->num_triangles;
2135 if (numsurfacelist >= maxsurfacelist)
2137 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2144 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2145 if (!r_showtrispass)
2146 renderstats.entities_triangles += counttriangles;