2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 // used for dlight push checking and other things
31 matrix4x4_t r_identitymatrix;
33 renderstats_t renderstats;
35 // true during envmap command capture
38 // maximum visible distance (recalculated from world box each frame)
40 // brightness of world lightmaps and related lighting
41 // (often reduced when world rtlights are enabled)
42 float r_lightmapintensity;
43 // whether to draw world lights realtime, dlights realtime, and their shadows
45 qboolean r_rtworldshadows;
47 qboolean r_rtdlightshadows;
50 // forces all rendering to draw triangle outlines
67 matrix4x4_t r_view_matrix;
74 cvar_t r_showtris = {0, "r_showtris", "0"};
75 cvar_t r_drawentities = {0, "r_drawentities","1"};
76 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
77 cvar_t r_speeds = {0, "r_speeds","0"};
78 cvar_t r_fullbright = {0, "r_fullbright","0"};
79 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
80 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
81 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
82 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
84 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
85 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
86 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
87 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
88 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
89 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
90 cvar_t gl_fogend = {0, "gl_fogend","0"};
92 cvar_t r_textureunits = {0, "r_textureunits", "32"};
94 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
95 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
96 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
98 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0"};
99 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "2"};
100 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "8"};
101 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
102 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"};
104 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1"};
106 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0"};
108 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
110 cvar_t r_test = {0, "r_test", "0"}; // used for testing renderer code changes, otherwise does nothing
112 rtexturepool_t *r_main_texturepool;
113 rtexture_t *r_bloom_texture_screen;
114 rtexture_t *r_bloom_texture_bloom;
115 rtexture_t *r_texture_blanknormalmap;
116 rtexture_t *r_texture_white;
117 rtexture_t *r_texture_black;
118 rtexture_t *r_texture_notexture;
119 rtexture_t *r_texture_whitecube;
120 rtexture_t *r_texture_normalizationcube;
122 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
125 for (i = 0;i < verts;i++)
136 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
139 for (i = 0;i < verts;i++)
151 float fog_density, fog_red, fog_green, fog_blue;
153 qboolean oldgl_fogenable;
154 void R_UpdateFog(void)
156 if (gamemode == GAME_NEHAHRA)
158 if (gl_fogenable.integer)
160 oldgl_fogenable = true;
161 fog_density = gl_fogdensity.value;
162 fog_red = gl_fogred.value;
163 fog_green = gl_foggreen.value;
164 fog_blue = gl_fogblue.value;
166 else if (oldgl_fogenable)
168 oldgl_fogenable = false;
177 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
178 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
179 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
184 fogdensity = -4000.0f / (fog_density * fog_density);
185 // fog color was already set
191 // FIXME: move this to client?
194 if (gamemode == GAME_NEHAHRA)
196 Cvar_Set("gl_fogenable", "0");
197 Cvar_Set("gl_fogdensity", "0.2");
198 Cvar_Set("gl_fogred", "0.3");
199 Cvar_Set("gl_foggreen", "0.3");
200 Cvar_Set("gl_fogblue", "0.3");
202 fog_density = fog_red = fog_green = fog_blue = 0.0f;
205 // FIXME: move this to client?
206 void FOG_registercvars(void)
208 if (gamemode == GAME_NEHAHRA)
210 Cvar_RegisterVariable (&gl_fogenable);
211 Cvar_RegisterVariable (&gl_fogdensity);
212 Cvar_RegisterVariable (&gl_fogred);
213 Cvar_RegisterVariable (&gl_foggreen);
214 Cvar_RegisterVariable (&gl_fogblue);
215 Cvar_RegisterVariable (&gl_fogstart);
216 Cvar_RegisterVariable (&gl_fogend);
220 static void R_BuildBlankTextures(void)
223 data[0] = 128; // normal X
224 data[1] = 128; // normal Y
225 data[2] = 255; // normal Z
226 data[3] = 128; // height
227 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
232 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
237 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
240 static void R_BuildNoTexture(void)
243 qbyte pix[16][16][4];
244 // this makes a light grey/dark grey checkerboard texture
245 for (y = 0;y < 16;y++)
247 for (x = 0;x < 16;x++)
249 if ((y < 8) ^ (x < 8))
265 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
268 static void R_BuildWhiteCube(void)
271 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
272 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
273 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
274 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
275 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
276 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
277 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
280 static void R_BuildNormalizationCube(void)
284 vec_t s, t, intensity;
286 qbyte data[6][NORMSIZE][NORMSIZE][4];
287 for (side = 0;side < 6;side++)
289 for (y = 0;y < NORMSIZE;y++)
291 for (x = 0;x < NORMSIZE;x++)
293 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
294 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
329 intensity = 127.0f / sqrt(DotProduct(v, v));
330 data[side][y][x][0] = 128.0f + intensity * v[0];
331 data[side][y][x][1] = 128.0f + intensity * v[1];
332 data[side][y][x][2] = 128.0f + intensity * v[2];
333 data[side][y][x][3] = 255;
337 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
340 void gl_main_start(void)
342 r_main_texturepool = R_AllocTexturePool();
343 r_bloom_texture_screen = NULL;
344 r_bloom_texture_bloom = NULL;
345 R_BuildBlankTextures();
347 if (gl_texturecubemap)
350 R_BuildNormalizationCube();
354 void gl_main_shutdown(void)
356 R_FreeTexturePool(&r_main_texturepool);
357 r_bloom_texture_screen = NULL;
358 r_bloom_texture_bloom = NULL;
359 r_texture_blanknormalmap = NULL;
360 r_texture_white = NULL;
361 r_texture_black = NULL;
362 r_texture_whitecube = NULL;
363 r_texture_normalizationcube = NULL;
366 extern void CL_ParseEntityLump(char *entitystring);
367 void gl_main_newmap(void)
369 // FIXME: move this code to client
371 char *entities, entname[MAX_QPATH];
375 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
376 l = (int)strlen(entname) - 4;
377 if (l >= 0 && !strcmp(entname + l, ".bsp"))
379 strcpy(entname + l, ".ent");
380 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true)))
382 CL_ParseEntityLump(entities);
387 if (cl.worldmodel->brush.entities)
388 CL_ParseEntityLump(cl.worldmodel->brush.entities);
392 void GL_Main_Init(void)
394 Matrix4x4_CreateIdentity(&r_identitymatrix);
395 // FIXME: move this to client?
397 Cvar_RegisterVariable(&r_showtris);
398 Cvar_RegisterVariable(&r_drawentities);
399 Cvar_RegisterVariable(&r_drawviewmodel);
400 Cvar_RegisterVariable(&r_speeds);
401 Cvar_RegisterVariable(&r_fullbrights);
402 Cvar_RegisterVariable(&r_wateralpha);
403 Cvar_RegisterVariable(&r_dynamic);
404 Cvar_RegisterVariable(&r_fullbright);
405 Cvar_RegisterVariable(&r_textureunits);
406 Cvar_RegisterVariable(&r_lerpsprites);
407 Cvar_RegisterVariable(&r_lerpmodels);
408 Cvar_RegisterVariable(&r_waterscroll);
409 Cvar_RegisterVariable(&r_drawcollisionbrushes);
410 Cvar_RegisterVariable(&r_bloom);
411 Cvar_RegisterVariable(&r_bloom_intensity);
412 Cvar_RegisterVariable(&r_bloom_blur);
413 Cvar_RegisterVariable(&r_bloom_resolution);
414 Cvar_RegisterVariable(&r_bloom_power);
415 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
416 Cvar_RegisterVariable(&developer_texturelogging);
417 Cvar_RegisterVariable(&gl_lightmaps);
418 Cvar_RegisterVariable(&r_test);
419 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
420 Cvar_SetValue("r_fullbrights", 0);
421 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
424 static vec3_t r_farclip_origin;
425 static vec3_t r_farclip_direction;
426 static vec_t r_farclip_directiondist;
427 static vec_t r_farclip_meshfarclip;
428 static int r_farclip_directionbit0;
429 static int r_farclip_directionbit1;
430 static int r_farclip_directionbit2;
432 // enlarge farclip to accomodate box
433 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
436 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
437 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
438 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
439 if (r_farclip_meshfarclip < d)
440 r_farclip_meshfarclip = d;
443 // return farclip value
444 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
448 VectorCopy(origin, r_farclip_origin);
449 VectorCopy(direction, r_farclip_direction);
450 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
451 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
452 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
453 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
454 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
456 if (r_refdef.worldmodel)
457 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
458 for (i = 0;i < r_refdef.numentities;i++)
459 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
461 return r_farclip_meshfarclip - r_farclip_directiondist;
464 extern void R_Textures_Init(void);
465 extern void GL_Draw_Init(void);
466 extern void GL_Main_Init(void);
467 extern void R_Shadow_Init(void);
468 extern void R_Sky_Init(void);
469 extern void GL_Surf_Init(void);
470 extern void R_Crosshairs_Init(void);
471 extern void R_Light_Init(void);
472 extern void R_Particles_Init(void);
473 extern void R_Explosion_Init(void);
474 extern void gl_backend_init(void);
475 extern void Sbar_Init(void);
476 extern void R_LightningBeams_Init(void);
477 extern void Mod_RenderInit(void);
479 void Render_Init(void)
495 R_LightningBeams_Init();
504 extern char *ENGINE_EXTENSIONS;
507 VID_CheckExtensions();
509 // LordHavoc: report supported extensions
510 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
512 // clear to black (loading plaque will be seen over this)
513 qglClearColor(0,0,0,1);
514 qglClear(GL_COLOR_BUFFER_BIT);
517 int R_CullBox(const vec3_t mins, const vec3_t maxs)
521 for (i = 0;i < 4;i++)
528 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
532 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
536 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
540 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
544 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
548 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
552 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
556 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
564 //==================================================================================
566 static void R_MarkEntities (void)
569 entity_render_t *ent;
571 if (!r_drawentities.integer)
574 r_refdef.worldentity->visframe = r_framecount;
575 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
576 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
578 // worldmodel can check visibility
579 for (i = 0;i < r_refdef.numentities;i++)
581 ent = r_refdef.entities[i];
582 // some of the renderer still relies on origin...
583 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
584 // some of the renderer still relies on scale...
585 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
586 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)))
588 R_UpdateEntLights(ent);
589 ent->visframe = r_framecount;
595 // no worldmodel or it can't check visibility
596 for (i = 0;i < r_refdef.numentities;i++)
598 ent = r_refdef.entities[i];
599 // some of the renderer still relies on origin...
600 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
601 // some of the renderer still relies on scale...
602 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
603 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
605 R_UpdateEntLights(ent);
606 ent->visframe = r_framecount;
612 // only used if skyrendermasked, and normally returns false
613 int R_DrawBrushModelsSky (void)
616 entity_render_t *ent;
618 if (!r_drawentities.integer)
622 for (i = 0;i < r_refdef.numentities;i++)
624 ent = r_refdef.entities[i];
625 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
627 ent->model->DrawSky(ent);
634 void R_DrawNoModel(entity_render_t *ent);
635 void R_DrawModels(void)
638 entity_render_t *ent;
640 if (!r_drawentities.integer)
643 for (i = 0;i < r_refdef.numentities;i++)
645 ent = r_refdef.entities[i];
646 if (ent->visframe == r_framecount)
648 renderstats.entities++;
649 if (ent->model && ent->model->Draw != NULL)
650 ent->model->Draw(ent);
657 static void R_SetFrustum(void)
659 // break apart the view matrix into vectors for various purposes
660 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
661 VectorNegate(r_viewleft, r_viewright);
663 // LordHavoc: note to all quake engine coders, the special case for 90
664 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
667 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
668 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
669 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
670 PlaneClassify(&frustum[0]);
672 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
673 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
674 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
675 PlaneClassify(&frustum[1]);
677 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
678 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
679 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
680 PlaneClassify(&frustum[2]);
682 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
683 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
684 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
685 PlaneClassify(&frustum[3]);
688 VectorCopy(r_viewforward, frustum[4].normal);
689 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
690 PlaneClassify(&frustum[4]);
693 static void R_BlendView(void)
697 if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
700 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
703 R_Mesh_Matrix(&r_identitymatrix);
704 // vertex coordinates for a quad that covers the screen exactly
705 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
706 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
707 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
708 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
709 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)
711 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
712 float xoffset, yoffset, r;
714 // set the (poorly named) screenwidth and screenheight variables to
715 // a power of 2 at least as large as the screen, these will define the
716 // size of the texture to allocate
717 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
718 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
719 // allocate textures as needed
720 if (!r_bloom_texture_screen)
721 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
722 if (!r_bloom_texture_bloom)
723 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
724 // set bloomwidth and bloomheight to the bloom resolution that will be
725 // used (often less than the screen resolution for faster rendering)
726 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
727 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
728 // set up a texcoord array for the full resolution screen image
729 // (we have to keep this around to copy back during final render)
730 varray_texcoord2f[0][0] = 0;
731 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
732 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
733 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
734 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
735 varray_texcoord2f[0][5] = 0;
736 varray_texcoord2f[0][6] = 0;
737 varray_texcoord2f[0][7] = 0;
738 // set up a texcoord array for the reduced resolution bloom image
739 // (which will be additive blended over the screen image)
740 varray_texcoord2f[1][0] = 0;
741 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
742 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
743 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
744 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
745 varray_texcoord2f[1][5] = 0;
746 varray_texcoord2f[1][6] = 0;
747 varray_texcoord2f[1][7] = 0;
748 memset(&m, 0, sizeof(m));
749 m.pointer_vertex = varray_vertex3f;
750 m.pointer_texcoord[0] = varray_texcoord2f[0];
751 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
753 // copy view into the full resolution screen image texture
755 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
756 renderstats.bloom_copypixels += r_view_width * r_view_height;
757 // now scale it down to the bloom size and raise to a power of itself
758 // to darken it (this leaves the really bright stuff bright, and
759 // everything else becomes very dark)
760 // TODO: optimize with multitexture or GLSL
761 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
762 GL_BlendFunc(GL_ONE, GL_ZERO);
763 GL_Color(1, 1, 1, 1);
764 R_Mesh_Draw(0, 4, 2, polygonelements);
765 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
766 // render multiple times with a multiply blendfunc to raise to a power
767 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
768 for (x = 1;x < r_bloom_power.integer;x++)
770 R_Mesh_Draw(0, 4, 2, polygonelements);
771 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
773 // we now have a darkened bloom image in the framebuffer, copy it into
774 // the bloom image texture for more processing
775 memset(&m, 0, sizeof(m));
776 m.pointer_vertex = varray_vertex3f;
777 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
778 m.pointer_texcoord[0] = varray_texcoord2f[2];
781 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
782 renderstats.bloom_copypixels += bloomwidth * bloomheight;
783 // blend on at multiple vertical offsets to achieve a vertical blur
784 // TODO: do offset blends using GLSL
785 range = r_bloom_blur.integer * bloomwidth / 320;
786 GL_BlendFunc(GL_ONE, GL_ZERO);
787 for (x = -range;x <= range;x++)
789 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
790 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
791 // compute a texcoord array with the specified x and y offset
792 varray_texcoord2f[2][0] = xoffset+0;
793 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
794 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
795 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
796 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
797 varray_texcoord2f[2][5] = yoffset+0;
798 varray_texcoord2f[2][6] = xoffset+0;
799 varray_texcoord2f[2][7] = yoffset+0;
800 // this r value looks like a 'dot' particle, fading sharply to
801 // black at the edges
802 // (probably not realistic but looks good enough)
803 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
806 GL_Color(r, r, r, 1);
807 R_Mesh_Draw(0, 4, 2, polygonelements);
808 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
809 GL_BlendFunc(GL_ONE, GL_ONE);
811 // copy the vertically blurred bloom view to a texture
813 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
814 renderstats.bloom_copypixels += bloomwidth * bloomheight;
815 // blend the vertically blurred image at multiple offsets horizontally
816 // to finish the blur effect
817 // TODO: do offset blends using GLSL
818 range = r_bloom_blur.integer * bloomwidth / 320;
819 GL_BlendFunc(GL_ONE, GL_ZERO);
820 for (x = -range;x <= range;x++)
822 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
823 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
824 // compute a texcoord array with the specified x and y offset
825 varray_texcoord2f[2][0] = xoffset+0;
826 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
827 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
828 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
829 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
830 varray_texcoord2f[2][5] = yoffset+0;
831 varray_texcoord2f[2][6] = xoffset+0;
832 varray_texcoord2f[2][7] = yoffset+0;
833 // this r value looks like a 'dot' particle, fading sharply to
834 // black at the edges
835 // (probably not realistic but looks good enough)
836 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
839 GL_Color(r, r, r, 1);
840 R_Mesh_Draw(0, 4, 2, polygonelements);
841 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
842 GL_BlendFunc(GL_ONE, GL_ONE);
844 // copy the blurred bloom view to a texture
846 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
847 renderstats.bloom_copypixels += bloomwidth * bloomheight;
848 // go back to full view area
849 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
850 // put the original screen image back in place and blend the bloom
852 memset(&m, 0, sizeof(m));
853 m.pointer_vertex = varray_vertex3f;
854 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
855 m.pointer_texcoord[0] = varray_texcoord2f[0];
857 dobloomblend = false;
859 // do both in one pass if possible
860 if (r_textureunits.integer >= 2 && gl_combine.integer)
862 dobloomblend = false;
863 m.texcombinergb[1] = GL_ADD;
864 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
865 m.pointer_texcoord[1] = varray_texcoord2f[1];
871 GL_BlendFunc(GL_ONE, GL_ZERO);
873 R_Mesh_Draw(0, 4, 2, polygonelements);
874 renderstats.bloom_drawpixels += r_view_width * r_view_height;
875 // now blend on the bloom texture if multipass
878 memset(&m, 0, sizeof(m));
879 m.pointer_vertex = varray_vertex3f;
880 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
881 m.pointer_texcoord[0] = varray_texcoord2f[1];
883 GL_BlendFunc(GL_ONE, GL_ONE);
885 R_Mesh_Draw(0, 4, 2, polygonelements);
886 renderstats.bloom_drawpixels += r_view_width * r_view_height;
889 if (r_refdef.viewblend[3] >= 0.01f)
891 // apply a color tint to the whole view
892 memset(&m, 0, sizeof(m));
893 m.pointer_vertex = varray_vertex3f;
895 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
896 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
897 R_Mesh_Draw(0, 4, 2, polygonelements);
901 void R_RenderScene(void);
903 matrix4x4_t r_waterscrollmatrix;
910 void R_RenderView(void)
912 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
913 return; //Host_Error ("R_RenderView: NULL worldmodel");
915 r_view_width = bound(0, r_refdef.width, vid.width);
916 r_view_height = bound(0, r_refdef.height, vid.height);
918 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
919 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
921 r_view_fov_x = bound(1, r_refdef.fov_x, 170);
922 r_view_fov_y = bound(1, r_refdef.fov_y, 170);
923 r_view_matrix = r_refdef.viewentitymatrix;
924 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
925 r_rtworld = r_shadow_realtime_world.integer;
926 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
927 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
928 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
929 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
931 // GL is weird because it's bottom to top, r_view_y is top to bottom
932 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
933 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
934 GL_ScissorTest(true);
939 R_TimeReport("setup");
941 qglDepthFunc(GL_LEQUAL);
942 qglPolygonOffset(0, 0);
943 qglEnable(GL_POLYGON_OFFSET_FILL);
947 qglPolygonOffset(0, 0);
948 qglDisable(GL_POLYGON_OFFSET_FILL);
951 R_TimeReport("blendview");
953 GL_Scissor(0, 0, vid.width, vid.height);
954 GL_ScissorTest(false);
957 extern void R_DrawLightningBeams (void);
958 void R_RenderScene(void)
960 // don't let sound skip if going slow
961 if (r_refdef.extraupdate)
966 R_MeshQueue_BeginScene();
968 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
972 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
973 if (r_rtworldshadows || r_rtdlightshadows)
974 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
976 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
978 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
980 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);
985 R_TimeReport("worldvis");
988 R_TimeReport("markentity");
990 R_Shadow_UpdateWorldLightSelection();
992 // don't let sound skip if going slow
993 if (r_refdef.extraupdate)
996 GL_ShowTrisColor(0.025, 0.025, 0, 1);
997 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
999 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1000 R_TimeReport("worldsky");
1003 if (R_DrawBrushModelsSky())
1004 R_TimeReport("bmodelsky");
1006 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1007 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1009 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1010 R_TimeReport("world");
1013 // don't let sound skip if going slow
1014 if (r_refdef.extraupdate)
1017 GL_ShowTrisColor(0, 0.015, 0, 1);
1020 R_TimeReport("models");
1022 // don't let sound skip if going slow
1023 if (r_refdef.extraupdate)
1026 GL_ShowTrisColor(0, 0, 0.033, 1);
1027 R_ShadowVolumeLighting(false);
1028 R_TimeReport("rtlights");
1030 // don't let sound skip if going slow
1031 if (r_refdef.extraupdate)
1034 GL_ShowTrisColor(0.1, 0, 0, 1);
1036 R_DrawLightningBeams();
1037 R_TimeReport("lightning");
1040 R_TimeReport("particles");
1043 R_TimeReport("explosions");
1045 R_MeshQueue_RenderTransparent();
1046 R_TimeReport("drawtrans");
1049 R_TimeReport("coronas");
1051 R_DrawWorldCrosshair();
1052 R_TimeReport("crosshair");
1054 R_MeshQueue_Render();
1055 R_MeshQueue_EndScene();
1057 if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1059 R_ShadowVolumeLighting(true);
1060 R_TimeReport("visiblevolume");
1063 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1065 // don't let sound skip if going slow
1066 if (r_refdef.extraupdate)
1071 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1074 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1076 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1077 GL_DepthMask(false);
1079 R_Mesh_Matrix(&r_identitymatrix);
1081 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1082 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1083 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1084 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1085 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1086 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1087 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1088 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1089 R_FillColors(color, 8, cr, cg, cb, ca);
1092 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1094 VectorSubtract(v, r_vieworigin, diff);
1095 f2 = exp(fogdensity/DotProduct(diff, diff));
1097 c[0] = c[0] * f1 + fogcolor[0] * f2;
1098 c[1] = c[1] * f1 + fogcolor[1] * f2;
1099 c[2] = c[2] * f1 + fogcolor[2] * f2;
1102 memset(&m, 0, sizeof(m));
1103 m.pointer_vertex = vertex3f;
1104 m.pointer_color = color;
1110 int nomodelelements[24] =
1122 float nomodelvertex3f[6*3] =
1132 float nomodelcolor4f[6*4] =
1134 0.0f, 0.0f, 0.5f, 1.0f,
1135 0.0f, 0.0f, 0.5f, 1.0f,
1136 0.0f, 0.5f, 0.0f, 1.0f,
1137 0.0f, 0.5f, 0.0f, 1.0f,
1138 0.5f, 0.0f, 0.0f, 1.0f,
1139 0.5f, 0.0f, 0.0f, 1.0f
1142 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1144 const entity_render_t *ent = (entity_render_t *)calldata1;
1146 float f1, f2, *c, diff[3];
1149 R_Mesh_Matrix(&ent->matrix);
1151 memset(&m, 0, sizeof(m));
1152 m.pointer_vertex = nomodelvertex3f;
1154 if (ent->flags & EF_ADDITIVE)
1156 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1157 GL_DepthMask(false);
1159 else if (ent->alpha < 1)
1161 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1162 GL_DepthMask(false);
1166 GL_BlendFunc(GL_ONE, GL_ZERO);
1169 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1172 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1173 m.pointer_color = color4f;
1174 VectorSubtract(ent->origin, r_vieworigin, diff);
1175 f2 = exp(fogdensity/DotProduct(diff, diff));
1177 for (i = 0, c = color4f;i < 6;i++, c += 4)
1179 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1180 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1181 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1185 else if (ent->alpha != 1)
1187 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1188 m.pointer_color = color4f;
1189 for (i = 0, c = color4f;i < 6;i++, c += 4)
1193 m.pointer_color = nomodelcolor4f;
1195 R_Mesh_Draw(0, 6, 8, nomodelelements);
1198 void R_DrawNoModel(entity_render_t *ent)
1200 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1201 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1203 // R_DrawNoModelCallback(ent, 0);
1206 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1208 vec3_t right1, right2, diff, normal;
1210 VectorSubtract (org2, org1, normal);
1212 // calculate 'right' vector for start
1213 VectorSubtract (r_vieworigin, org1, diff);
1214 CrossProduct (normal, diff, right1);
1215 VectorNormalize (right1);
1217 // calculate 'right' vector for end
1218 VectorSubtract (r_vieworigin, org2, diff);
1219 CrossProduct (normal, diff, right2);
1220 VectorNormalize (right2);
1222 vert[ 0] = org1[0] + width * right1[0];
1223 vert[ 1] = org1[1] + width * right1[1];
1224 vert[ 2] = org1[2] + width * right1[2];
1225 vert[ 3] = org1[0] - width * right1[0];
1226 vert[ 4] = org1[1] - width * right1[1];
1227 vert[ 5] = org1[2] - width * right1[2];
1228 vert[ 6] = org2[0] - width * right2[0];
1229 vert[ 7] = org2[1] - width * right2[1];
1230 vert[ 8] = org2[2] - width * right2[2];
1231 vert[ 9] = org2[0] + width * right2[0];
1232 vert[10] = org2[1] + width * right2[1];
1233 vert[11] = org2[2] + width * right2[2];
1236 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1238 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)
1245 VectorSubtract(origin, r_vieworigin, diff);
1246 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1249 R_Mesh_Matrix(&r_identitymatrix);
1250 GL_BlendFunc(blendfunc1, blendfunc2);
1251 GL_DepthMask(false);
1252 GL_DepthTest(!depthdisable);
1254 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1255 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1256 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1257 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1258 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1259 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1260 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1261 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1262 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1263 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1264 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1265 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1267 memset(&m, 0, sizeof(m));
1268 m.tex[0] = R_GetTexture(texture);
1269 m.pointer_texcoord[0] = spritetexcoord2f;
1270 m.pointer_vertex = varray_vertex3f;
1272 GL_Color(cr, cg, cb, ca);
1273 R_Mesh_Draw(0, 4, 2, polygonelements);
1276 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1280 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1281 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1283 if (i == mesh->numvertices)
1285 if (mesh->numvertices < mesh->maxvertices)
1287 VectorCopy(v, vertex3f);
1288 mesh->numvertices++;
1290 return mesh->numvertices;
1296 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1300 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1301 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1302 e = mesh->element3i + mesh->numtriangles * 3;
1303 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1305 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1306 if (mesh->numtriangles < mesh->maxtriangles)
1311 mesh->numtriangles++;
1313 element[1] = element[2];
1317 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1319 int planenum, planenum2;
1322 mplane_t *plane, *plane2;
1323 float temppoints[2][256*3];
1324 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1328 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1329 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1331 if (planenum2 == planenum)
1333 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);
1336 if (tempnumpoints < 3)
1338 // generate elements forming a triangle fan for this polygon
1339 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1343 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)
1345 texturelayer_t *layer;
1346 layer = t->currentlayers + t->currentnumlayers++;
1348 layer->depthmask = depthmask;
1349 layer->blendfunc1 = blendfunc1;
1350 layer->blendfunc2 = blendfunc2;
1351 layer->texture = texture;
1352 layer->texmatrix = *matrix;
1353 layer->color[0] = r;
1354 layer->color[1] = g;
1355 layer->color[2] = b;
1356 layer->color[3] = a;
1359 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1361 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1362 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1366 texture_t *texture = t;
1367 model_t *model = ent->model;
1368 int s = ent->skinnum;
1369 if ((unsigned int)s >= (unsigned int)model->numskins)
1371 if (model->skinscenes)
1373 if (model->skinscenes[s].framecount > 1)
1374 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1376 s = model->skinscenes[s].firstframe;
1379 t = t + s * model->num_surfaces;
1381 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];
1382 texture->currentframe = t;
1385 t->currentmaterialflags = t->basematerialflags;
1386 currentalpha = ent->alpha;
1387 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1388 currentalpha *= r_wateralpha.value;
1389 if (!(ent->flags & RENDER_LIGHT))
1390 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1391 if (ent->effects & EF_ADDITIVE)
1392 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1393 else if (currentalpha < 1)
1394 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1395 if (ent->effects & EF_NODEPTHTEST)
1396 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1397 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1398 t->currenttexmatrix = r_waterscrollmatrix;
1400 t->currenttexmatrix = r_identitymatrix;
1401 t->currentnumlayers = 0;
1402 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1404 if (gl_lightmaps.integer)
1405 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1406 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1408 // transparent sky would be ridiculous
1409 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1410 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1414 int blendfunc1, blendfunc2, depthmask;
1415 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1417 blendfunc1 = GL_SRC_ALPHA;
1418 blendfunc2 = GL_ONE;
1421 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1423 blendfunc1 = GL_SRC_ALPHA;
1424 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1429 blendfunc1 = GL_ONE;
1430 blendfunc2 = GL_ZERO;
1433 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1435 rtexture_t *currentbasetexture;
1437 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1438 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1439 currentbasetexture = (ent->colormap < 0 && t->skin.merged) ? t->skin.merged : t->skin.base;
1440 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1442 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], currentalpha);
1443 if (ent->colormap >= 0 && t->skin.pants)
1444 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);
1445 if (ent->colormap >= 0 && t->skin.shirt)
1446 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);
1452 // q3bsp has no lightmap updates, so the lightstylevalue that
1453 // would normally be baked into the lightmaptexture must be
1454 // applied to the color
1455 if (ent->model->type == mod_brushq3)
1456 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1457 // transparent and fullbright are not affected by r_lightmapintensity
1458 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1459 colorscale *= r_lightmapintensity;
1460 if (r_textureunits.integer >= 2 && gl_combine.integer)
1461 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);
1462 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1463 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);
1465 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);
1466 if (r_ambient.value >= (1.0f/64.0f))
1467 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);
1468 if (ent->colormap >= 0 && t->skin.pants)
1470 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);
1471 if (r_ambient.value >= (1.0f/64.0f))
1472 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);
1474 if (ent->colormap >= 0 && t->skin.shirt)
1476 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);
1477 if (r_ambient.value >= (1.0f/64.0f))
1478 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);
1481 if (t->skin.glow != NULL)
1482 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, currentalpha);
1483 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1485 // if this is opaque use alpha blend which will darken the earlier
1488 // if this is an alpha blended material, all the earlier passes
1489 // were darkened by fog already, so we only need to add the fog
1490 // color ontop through the fog mask texture
1492 // if this is an additive blended material, all the earlier passes
1493 // were darkened by fog already, and we should not add fog color
1494 // (because the background was not darkened, there is no fog color
1495 // that was lost behind it).
1496 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);
1503 void R_UpdateAllTextureInfo(entity_render_t *ent)
1507 for (i = 0;i < ent->model->num_textures;i++)
1508 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1511 float *rsurface_vertex3f;
1512 float *rsurface_svector3f;
1513 float *rsurface_tvector3f;
1514 float *rsurface_normal3f;
1515 float *rsurface_lightmapcolor4f;
1517 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1520 float center[3], forward[3], right[3], up[3], v[4][3];
1521 matrix4x4_t matrix1, imatrix1;
1522 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1524 rsurface_vertex3f = varray_vertex3f;
1525 rsurface_svector3f = NULL;
1526 rsurface_tvector3f = NULL;
1527 rsurface_normal3f = NULL;
1528 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1532 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1533 rsurface_svector3f = surface->groupmesh->data_svector3f;
1534 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1535 rsurface_normal3f = surface->groupmesh->data_normal3f;
1537 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1539 if (!rsurface_svector3f)
1541 rsurface_svector3f = varray_svector3f;
1542 rsurface_tvector3f = varray_tvector3f;
1543 rsurface_normal3f = varray_normal3f;
1544 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);
1546 // a single autosprite surface can contain multiple sprites...
1547 VectorClear(forward);
1549 VectorSet(up, 0, 0, 1);
1550 for (j = 0;j < surface->num_vertices - 3;j += 4)
1552 VectorClear(center);
1553 for (i = 0;i < 4;i++)
1554 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1555 VectorScale(center, 0.25f, center);
1556 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1557 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);
1558 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1559 for (i = 0;i < 4;i++)
1560 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1561 forward[0] = modelorg[0] - center[0];
1562 forward[1] = modelorg[1] - center[1];
1563 VectorNormalize(forward);
1564 right[0] = forward[1];
1565 right[1] = -forward[0];
1566 for (i = 0;i < 4;i++)
1567 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1569 rsurface_vertex3f = varray_vertex3f;
1570 rsurface_svector3f = NULL;
1571 rsurface_tvector3f = NULL;
1572 rsurface_normal3f = NULL;
1574 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1576 if (!rsurface_svector3f)
1578 rsurface_svector3f = varray_svector3f;
1579 rsurface_tvector3f = varray_tvector3f;
1580 rsurface_normal3f = varray_normal3f;
1581 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);
1583 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1584 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1585 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1586 // a single autosprite surface can contain multiple sprites...
1587 for (j = 0;j < surface->num_vertices - 3;j += 4)
1589 VectorClear(center);
1590 for (i = 0;i < 4;i++)
1591 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1592 VectorScale(center, 0.25f, center);
1593 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1594 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);
1595 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1596 for (i = 0;i < 4;i++)
1597 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1598 for (i = 0;i < 4;i++)
1599 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1601 rsurface_vertex3f = varray_vertex3f;
1602 rsurface_svector3f = NULL;
1603 rsurface_tvector3f = NULL;
1604 rsurface_normal3f = NULL;
1606 R_Mesh_VertexPointer(rsurface_vertex3f);
1609 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)
1618 vec4_t ambientcolor4f;
1619 vec3_t diffusecolor;
1620 vec3_t diffusenormal;
1621 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1623 rsurface_lightmapcolor4f = varray_color4f;
1624 if (rsurface_normal3f == NULL)
1626 rsurface_normal3f = varray_normal3f;
1627 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);
1629 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);
1638 r = ambientcolor4f[0];
1639 g = ambientcolor4f[1];
1640 b = ambientcolor4f[2];
1641 a = ambientcolor4f[3];
1642 rsurface_lightmapcolor4f = NULL;
1645 else if (lightmode >= 1)
1647 if (surface->lightmapinfo)
1649 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1651 const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1654 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1655 VectorScale(lm, scale, c);
1656 if (surface->lightmapinfo->styles[1] != 255)
1658 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1660 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1661 VectorMA(c, scale, lm, c);
1662 if (surface->lightmapinfo->styles[2] != 255)
1665 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1666 VectorMA(c, scale, lm, c);
1667 if (surface->lightmapinfo->styles[3] != 255)
1670 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1671 VectorMA(c, scale, lm, c);
1679 rsurface_lightmapcolor4f = varray_color4f;
1682 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1685 rsurface_lightmapcolor4f = NULL;
1688 if (rsurface_lightmapcolor4f)
1690 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)
1692 VectorSubtract(v, modelorg, diff);
1693 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1702 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)
1704 VectorSubtract(v, modelorg, diff);
1705 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1712 rsurface_lightmapcolor4f = varray_color4f;
1714 if (applycolor && rsurface_lightmapcolor4f)
1716 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)
1723 rsurface_lightmapcolor4f = varray_color4f;
1725 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1726 GL_Color(r, g, b, a);
1730 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1732 int texturesurfaceindex;
1734 const msurface_t *surface;
1735 qboolean applycolor;
1737 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1739 renderstats.entities_surfaces += texturenumsurfaces;
1740 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1741 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1742 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1743 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1744 qglDisable(GL_CULL_FACE);
1745 if (texture->currentnumlayers)
1748 texturelayer_t *layer;
1749 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1752 int layertexrgbscale;
1753 GL_DepthMask(layer->depthmask);
1754 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1755 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1757 layertexrgbscale = 4;
1758 VectorScale(layer->color, 0.25f, layercolor);
1760 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
1762 layertexrgbscale = 2;
1763 VectorScale(layer->color, 0.5f, layercolor);
1767 layertexrgbscale = 1;
1768 VectorScale(layer->color, 1.0f, layercolor);
1770 layercolor[3] = layer->color[3];
1771 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1772 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
1773 switch (layer->type)
1775 case TEXTURELAYERTYPE_SKY:
1778 skyrendernow = false;
1779 if (skyrendermasked)
1782 // restore entity matrix and GL_Color
1783 R_Mesh_Matrix(&ent->matrix);
1784 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1787 // LordHavoc: HalfLife maps have freaky skypolys...
1788 //if (!ent->model->brush.ishlbsp)
1790 if (skyrendermasked)
1792 // depth-only (masking)
1793 GL_ColorMask(0,0,0,0);
1794 // just to make sure that braindead drivers don't draw anything
1795 // despite that colormask...
1796 GL_BlendFunc(GL_ZERO, GL_ONE);
1801 GL_BlendFunc(GL_ONE, GL_ZERO);
1803 memset(&m, 0, sizeof(m));
1805 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1807 surface = texturesurfacelist[texturesurfaceindex];
1808 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1809 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1810 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1811 GL_LockArrays(0, 0);
1813 if (skyrendermasked)
1814 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1817 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
1818 memset(&m, 0, sizeof(m));
1819 m.tex[1] = R_GetTexture(layer->texture);
1820 m.texmatrix[1] = layer->texmatrix;
1821 m.texrgbscale[1] = layertexrgbscale;
1822 m.pointer_color = varray_color4f;
1824 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1826 surface = texturesurfacelist[texturesurfaceindex];
1827 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1828 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1829 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1832 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1833 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1835 else if (surface->lightmaptexture)
1837 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1838 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1842 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1843 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1845 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1846 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1847 GL_LockArrays(0, 0);
1850 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
1851 memset(&m, 0, sizeof(m));
1852 m.tex[0] = R_GetTexture(layer->texture);
1853 m.texmatrix[0] = layer->texmatrix;
1854 m.pointer_color = varray_color4f;
1855 m.texrgbscale[0] = layertexrgbscale;
1857 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1859 surface = texturesurfacelist[texturesurfaceindex];
1860 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1861 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1864 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1865 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
1867 else if (surface->lightmaptexture)
1869 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1870 R_Mesh_ColorPointer(NULL);
1874 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1875 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
1877 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1878 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1879 GL_LockArrays(0, 0);
1881 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1882 memset(&m, 0, sizeof(m));
1883 m.tex[0] = R_GetTexture(layer->texture);
1884 m.texmatrix[0] = layer->texmatrix;
1885 m.pointer_color = varray_color4f;
1886 m.texrgbscale[0] = layertexrgbscale;
1888 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1890 surface = texturesurfacelist[texturesurfaceindex];
1891 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1892 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1893 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1894 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1895 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1896 GL_LockArrays(0, 0);
1899 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
1900 memset(&m, 0, sizeof(m));
1901 m.tex[0] = R_GetTexture(layer->texture);
1902 m.texmatrix[0] = layer->texmatrix;
1903 m.texrgbscale[0] = layertexrgbscale;
1904 m.pointer_color = varray_color4f;
1906 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1908 surface = texturesurfacelist[texturesurfaceindex];
1909 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1910 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1911 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1912 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1913 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1914 GL_LockArrays(0, 0);
1917 case TEXTURELAYERTYPE_TEXTURE:
1918 memset(&m, 0, sizeof(m));
1919 m.tex[0] = R_GetTexture(layer->texture);
1920 m.texmatrix[0] = layer->texmatrix;
1921 m.pointer_color = varray_color4f;
1922 m.texrgbscale[0] = layertexrgbscale;
1924 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1926 surface = texturesurfacelist[texturesurfaceindex];
1927 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1928 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1929 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1930 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1931 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1932 GL_LockArrays(0, 0);
1935 case TEXTURELAYERTYPE_FOG:
1936 memset(&m, 0, sizeof(m));
1939 m.tex[0] = R_GetTexture(layer->texture);
1940 m.texmatrix[0] = layer->texmatrix;
1943 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1948 surface = texturesurfacelist[texturesurfaceindex];
1949 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1951 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1952 R_Mesh_ColorPointer(varray_color4f);
1953 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)
1955 VectorSubtract(v, modelorg, diff);
1956 f = exp(fogdensity/DotProduct(diff, diff));
1957 c[0] = layercolor[0];
1958 c[1] = layercolor[1];
1959 c[2] = layercolor[2];
1960 c[3] = f * layercolor[3];
1962 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1963 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1964 GL_LockArrays(0, 0);
1968 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
1970 // if trying to do overbright on first pass of an opaque surface
1971 // when combine is not supported, brighten as a post process
1972 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
1975 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1976 GL_Color(1, 1, 1, 1);
1977 memset(&m, 0, sizeof(m));
1979 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1981 surface = texturesurfacelist[texturesurfaceindex];
1982 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1983 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1984 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
1985 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1986 GL_LockArrays(0, 0);
1991 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1992 qglEnable(GL_CULL_FACE);
1995 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
1997 const entity_render_t *ent = (entity_render_t *)calldata1;
1998 const msurface_t *surface = ent->model->data_surfaces + calldata2;
2002 texture = surface->texture;
2003 if (texture->basematerialflags & MATERIALFLAG_SKY)
2004 return; // transparent sky is too difficult
2005 R_UpdateTextureInfo(ent, texture);
2007 R_Mesh_Matrix(&ent->matrix);
2008 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2009 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2012 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2014 int texturesurfaceindex;
2015 const msurface_t *surface;
2016 vec3_t tempcenter, center;
2017 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2019 // drawing sky transparently would be too difficult
2020 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2022 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2024 surface = texturesurfacelist[texturesurfaceindex];
2025 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2026 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2027 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2028 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2029 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2034 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2037 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2038 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2040 int i, j, f, flagsmask;
2041 int counttriangles = 0;
2042 msurface_t *surface, **surfacechain;
2043 texture_t *t, *texture;
2044 model_t *model = ent->model;
2046 const int maxsurfacelist = 1024;
2047 int numsurfacelist = 0;
2048 const msurface_t *surfacelist[1024];
2051 R_Mesh_Matrix(&ent->matrix);
2052 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2054 // update light styles
2055 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2057 for (i = 0;i < model->brushq1.light_styles;i++)
2059 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2061 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2062 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2063 for (;(surface = *surfacechain);surfacechain++)
2064 surface->cached_dlight = true;
2069 R_UpdateAllTextureInfo(ent);
2070 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2075 if (ent == r_refdef.worldentity)
2077 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2079 if (!r_worldsurfacevisible[j])
2081 if (t != surface->texture)
2085 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2088 t = surface->texture;
2089 texture = t->currentframe;
2090 f = texture->currentmaterialflags & flagsmask;
2092 if (f && surface->num_triangles)
2094 // if lightmap parameters changed, rebuild lightmap texture
2095 if (surface->cached_dlight && surface->lightmapinfo->samples)
2096 R_BuildLightMap(ent, surface);
2097 // add face to draw list
2098 surfacelist[numsurfacelist++] = surface;
2099 counttriangles += surface->num_triangles;
2100 if (numsurfacelist >= maxsurfacelist)
2102 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2110 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2112 if (t != surface->texture)
2116 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2119 t = surface->texture;
2120 texture = t->currentframe;
2121 f = texture->currentmaterialflags & flagsmask;
2123 if (f && surface->num_triangles)
2125 // if lightmap parameters changed, rebuild lightmap texture
2126 if (surface->cached_dlight && surface->lightmapinfo->samples)
2127 R_BuildLightMap(ent, surface);
2128 // add face to draw list
2129 surfacelist[numsurfacelist++] = surface;
2130 counttriangles += surface->num_triangles;
2131 if (numsurfacelist >= maxsurfacelist)
2133 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2140 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2141 if (!r_showtrispass)
2142 renderstats.entities_triangles += counttriangles;