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 int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights, c_meshs, c_meshelements, c_rt_lights, c_rt_clears, c_rt_scissored, c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris, c_rtcached_shadowmeshes, c_rtcached_shadowtris, c_bloom, c_bloomcopies, c_bloomcopypixels, c_bloomdraws, c_bloomdrawpixels;
35 // true during envmap command capture
38 // maximum visible distance (recalculated from world box each frame)
40 // brightness of world lightmaps and related lighting
41 // (often reduced when world rtlights are enabled)
42 float r_lightmapintensity;
43 // whether to draw world lights realtime, dlights realtime, and their shadows
45 qboolean r_rtworldshadows;
47 qboolean r_rtdlightshadows;
50 // forces all rendering to draw triangle outlines
67 matrix4x4_t r_view_matrix;
74 // 8.8 fraction of base light value
75 unsigned short d_lightstylevalue[256];
77 cvar_t r_showtris = {0, "r_showtris", "0"};
78 cvar_t r_drawentities = {0, "r_drawentities","1"};
79 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
80 cvar_t r_speeds = {0, "r_speeds","0"};
81 cvar_t r_fullbright = {0, "r_fullbright","0"};
82 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
83 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
84 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
85 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
87 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
88 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
89 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
90 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
91 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
92 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
93 cvar_t gl_fogend = {0, "gl_fogend","0"};
95 cvar_t r_textureunits = {0, "r_textureunits", "32"};
97 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
98 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
99 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
101 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0"};
102 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "2"};
103 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "8"};
104 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
105 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"};
107 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1"};
109 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0"};
111 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
113 cvar_t r_test = {0, "r_test", "0"}; // used for testing renderer code changes, otherwise does nothing
115 rtexturepool_t *r_main_texturepool;
116 rtexture_t *r_bloom_texture_screen;
117 rtexture_t *r_bloom_texture_bloom;
118 rtexture_t *r_texture_blanknormalmap;
119 rtexture_t *r_texture_white;
120 rtexture_t *r_texture_black;
121 rtexture_t *r_texture_notexture;
122 rtexture_t *r_texture_whitecube;
123 rtexture_t *r_texture_normalizationcube;
125 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
128 for (i = 0;i < verts;i++)
139 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
142 for (i = 0;i < verts;i++)
154 float fog_density, fog_red, fog_green, fog_blue;
156 qboolean oldgl_fogenable;
157 void R_UpdateFog(void)
159 if (gamemode == GAME_NEHAHRA)
161 if (gl_fogenable.integer)
163 oldgl_fogenable = true;
164 fog_density = gl_fogdensity.value;
165 fog_red = gl_fogred.value;
166 fog_green = gl_foggreen.value;
167 fog_blue = gl_fogblue.value;
169 else if (oldgl_fogenable)
171 oldgl_fogenable = false;
180 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
181 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
182 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
187 fogdensity = -4000.0f / (fog_density * fog_density);
188 // fog color was already set
194 // FIXME: move this to client?
197 if (gamemode == GAME_NEHAHRA)
199 Cvar_Set("gl_fogenable", "0");
200 Cvar_Set("gl_fogdensity", "0.2");
201 Cvar_Set("gl_fogred", "0.3");
202 Cvar_Set("gl_foggreen", "0.3");
203 Cvar_Set("gl_fogblue", "0.3");
205 fog_density = fog_red = fog_green = fog_blue = 0.0f;
208 // FIXME: move this to client?
209 void FOG_registercvars(void)
211 if (gamemode == GAME_NEHAHRA)
213 Cvar_RegisterVariable (&gl_fogenable);
214 Cvar_RegisterVariable (&gl_fogdensity);
215 Cvar_RegisterVariable (&gl_fogred);
216 Cvar_RegisterVariable (&gl_foggreen);
217 Cvar_RegisterVariable (&gl_fogblue);
218 Cvar_RegisterVariable (&gl_fogstart);
219 Cvar_RegisterVariable (&gl_fogend);
223 static void R_BuildBlankTextures(void)
226 data[0] = 128; // normal X
227 data[1] = 128; // normal Y
228 data[2] = 255; // normal Z
229 data[3] = 128; // height
230 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
235 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
240 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
243 static void R_BuildNoTexture(void)
246 qbyte pix[16][16][4];
247 // this makes a light grey/dark grey checkerboard texture
248 for (y = 0;y < 16;y++)
250 for (x = 0;x < 16;x++)
252 if ((y < 8) ^ (x < 8))
268 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
271 static void R_BuildWhiteCube(void)
274 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
275 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
276 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
277 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
278 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
279 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
280 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
283 static void R_BuildNormalizationCube(void)
287 vec_t s, t, intensity;
289 qbyte data[6][NORMSIZE][NORMSIZE][4];
290 for (side = 0;side < 6;side++)
292 for (y = 0;y < NORMSIZE;y++)
294 for (x = 0;x < NORMSIZE;x++)
296 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
297 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
332 intensity = 127.0f / sqrt(DotProduct(v, v));
333 data[side][y][x][0] = 128.0f + intensity * v[0];
334 data[side][y][x][1] = 128.0f + intensity * v[1];
335 data[side][y][x][2] = 128.0f + intensity * v[2];
336 data[side][y][x][3] = 255;
340 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
343 void gl_main_start(void)
345 r_main_texturepool = R_AllocTexturePool();
346 r_bloom_texture_screen = NULL;
347 r_bloom_texture_bloom = NULL;
348 R_BuildBlankTextures();
350 if (gl_texturecubemap)
353 R_BuildNormalizationCube();
357 void gl_main_shutdown(void)
359 R_FreeTexturePool(&r_main_texturepool);
360 r_bloom_texture_screen = NULL;
361 r_bloom_texture_bloom = NULL;
362 r_texture_blanknormalmap = NULL;
363 r_texture_white = NULL;
364 r_texture_black = NULL;
365 r_texture_whitecube = NULL;
366 r_texture_normalizationcube = NULL;
369 extern void CL_ParseEntityLump(char *entitystring);
370 void gl_main_newmap(void)
372 // FIXME: move this code to client
374 char *entities, entname[MAX_QPATH];
378 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
379 l = (int)strlen(entname) - 4;
380 if (l >= 0 && !strcmp(entname + l, ".bsp"))
382 strcpy(entname + l, ".ent");
383 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true)))
385 CL_ParseEntityLump(entities);
390 if (cl.worldmodel->brush.entities)
391 CL_ParseEntityLump(cl.worldmodel->brush.entities);
395 void GL_Main_Init(void)
397 Matrix4x4_CreateIdentity(&r_identitymatrix);
398 // FIXME: move this to client?
400 Cvar_RegisterVariable(&r_showtris);
401 Cvar_RegisterVariable(&r_drawentities);
402 Cvar_RegisterVariable(&r_drawviewmodel);
403 Cvar_RegisterVariable(&r_speeds);
404 Cvar_RegisterVariable(&r_fullbrights);
405 Cvar_RegisterVariable(&r_wateralpha);
406 Cvar_RegisterVariable(&r_dynamic);
407 Cvar_RegisterVariable(&r_fullbright);
408 Cvar_RegisterVariable(&r_textureunits);
409 Cvar_RegisterVariable(&r_lerpsprites);
410 Cvar_RegisterVariable(&r_lerpmodels);
411 Cvar_RegisterVariable(&r_waterscroll);
412 Cvar_RegisterVariable(&r_drawcollisionbrushes);
413 Cvar_RegisterVariable(&r_bloom);
414 Cvar_RegisterVariable(&r_bloom_intensity);
415 Cvar_RegisterVariable(&r_bloom_blur);
416 Cvar_RegisterVariable(&r_bloom_resolution);
417 Cvar_RegisterVariable(&r_bloom_power);
418 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
419 Cvar_RegisterVariable(&developer_texturelogging);
420 Cvar_RegisterVariable(&gl_lightmaps);
421 Cvar_RegisterVariable(&r_test);
422 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
423 Cvar_SetValue("r_fullbrights", 0);
424 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
427 static vec3_t r_farclip_origin;
428 static vec3_t r_farclip_direction;
429 static vec_t r_farclip_directiondist;
430 static vec_t r_farclip_meshfarclip;
431 static int r_farclip_directionbit0;
432 static int r_farclip_directionbit1;
433 static int r_farclip_directionbit2;
435 // enlarge farclip to accomodate box
436 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
439 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
440 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
441 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
442 if (r_farclip_meshfarclip < d)
443 r_farclip_meshfarclip = d;
446 // return farclip value
447 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
451 VectorCopy(origin, r_farclip_origin);
452 VectorCopy(direction, r_farclip_direction);
453 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
454 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
455 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
456 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
457 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
459 if (r_refdef.worldmodel)
460 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
461 for (i = 0;i < r_refdef.numentities;i++)
462 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
464 return r_farclip_meshfarclip - r_farclip_directiondist;
467 extern void R_Textures_Init(void);
468 extern void GL_Draw_Init(void);
469 extern void GL_Main_Init(void);
470 extern void R_Shadow_Init(void);
471 extern void R_Sky_Init(void);
472 extern void GL_Surf_Init(void);
473 extern void R_Crosshairs_Init(void);
474 extern void R_Light_Init(void);
475 extern void R_Particles_Init(void);
476 extern void R_Explosion_Init(void);
477 extern void gl_backend_init(void);
478 extern void Sbar_Init(void);
479 extern void R_LightningBeams_Init(void);
480 extern void Mod_RenderInit(void);
482 void Render_Init(void)
498 R_LightningBeams_Init();
507 extern char *ENGINE_EXTENSIONS;
510 VID_CheckExtensions();
512 // LordHavoc: report supported extensions
513 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
515 // clear to black (loading plaque will be seen over this)
516 qglClearColor(0,0,0,1);
517 qglClear(GL_COLOR_BUFFER_BIT);
520 int R_CullBox(const vec3_t mins, const vec3_t maxs)
524 for (i = 0;i < 4;i++)
531 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
535 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
539 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
543 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
547 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
551 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
555 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
559 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
567 //==================================================================================
569 static void R_MarkEntities (void)
572 entity_render_t *ent;
574 if (!r_drawentities.integer)
577 r_refdef.worldentity->visframe = r_framecount;
578 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
579 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
581 // worldmodel can check visibility
582 for (i = 0;i < r_refdef.numentities;i++)
584 ent = r_refdef.entities[i];
585 Mod_CheckLoaded(ent->model);
586 // some of the renderer still relies on origin...
587 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
588 // some of the renderer still relies on scale...
589 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
590 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_worldleafvisible, ent->mins, ent->maxs)))
592 R_UpdateEntLights(ent);
593 ent->visframe = r_framecount;
599 // no worldmodel or it can't check visibility
600 for (i = 0;i < r_refdef.numentities;i++)
602 ent = r_refdef.entities[i];
603 Mod_CheckLoaded(ent->model);
604 // some of the renderer still relies on origin...
605 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
606 // some of the renderer still relies on scale...
607 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
608 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
610 R_UpdateEntLights(ent);
611 ent->visframe = r_framecount;
617 // only used if skyrendermasked, and normally returns false
618 int R_DrawBrushModelsSky (void)
621 entity_render_t *ent;
623 if (!r_drawentities.integer)
627 for (i = 0;i < r_refdef.numentities;i++)
629 ent = r_refdef.entities[i];
630 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
632 ent->model->DrawSky(ent);
639 void R_DrawNoModel(entity_render_t *ent);
640 void R_DrawModels(void)
643 entity_render_t *ent;
645 if (!r_drawentities.integer)
648 for (i = 0;i < r_refdef.numentities;i++)
650 ent = r_refdef.entities[i];
651 if (ent->visframe == r_framecount)
653 if (ent->model && ent->model->Draw != NULL)
654 ent->model->Draw(ent);
661 static void R_SetFrustum(void)
663 // break apart the view matrix into vectors for various purposes
664 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
665 VectorNegate(r_viewleft, r_viewright);
667 // LordHavoc: note to all quake engine coders, the special case for 90
668 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
671 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
672 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
673 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
674 PlaneClassify(&frustum[0]);
676 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
677 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
678 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
679 PlaneClassify(&frustum[1]);
681 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
682 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
683 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
684 PlaneClassify(&frustum[2]);
686 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
687 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
688 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
689 PlaneClassify(&frustum[3]);
692 VectorCopy(r_viewforward, frustum[4].normal);
693 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
694 PlaneClassify(&frustum[4]);
697 static void R_BlendView(void)
701 if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
704 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
707 R_Mesh_Matrix(&r_identitymatrix);
708 // vertex coordinates for a quad that covers the screen exactly
709 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
710 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
711 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
712 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
713 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)
715 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
716 float xoffset, yoffset, r;
718 // set the (poorly named) screenwidth and screenheight variables to
719 // a power of 2 at least as large as the screen, these will define the
720 // size of the texture to allocate
721 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
722 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
723 // allocate textures as needed
724 if (!r_bloom_texture_screen)
725 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
726 if (!r_bloom_texture_bloom)
727 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
728 // set bloomwidth and bloomheight to the bloom resolution that will be
729 // used (often less than the screen resolution for faster rendering)
730 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
731 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
732 // set up a texcoord array for the full resolution screen image
733 // (we have to keep this around to copy back during final render)
734 varray_texcoord2f[0][0] = 0;
735 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
736 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
737 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
738 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
739 varray_texcoord2f[0][5] = 0;
740 varray_texcoord2f[0][6] = 0;
741 varray_texcoord2f[0][7] = 0;
742 // set up a texcoord array for the reduced resolution bloom image
743 // (which will be additive blended over the screen image)
744 varray_texcoord2f[1][0] = 0;
745 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
746 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
747 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
748 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
749 varray_texcoord2f[1][5] = 0;
750 varray_texcoord2f[1][6] = 0;
751 varray_texcoord2f[1][7] = 0;
752 memset(&m, 0, sizeof(m));
753 m.pointer_vertex = varray_vertex3f;
754 m.pointer_texcoord[0] = varray_texcoord2f[0];
755 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
757 // copy view into the full resolution screen image texture
759 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
761 c_bloomcopypixels += r_view_width * r_view_height;
762 // now scale it down to the bloom size and raise to a power of itself
763 // to darken it (this leaves the really bright stuff bright, and
764 // everything else becomes very dark)
765 // TODO: optimize with multitexture or GLSL
766 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
767 GL_BlendFunc(GL_ONE, GL_ZERO);
768 GL_Color(1, 1, 1, 1);
769 R_Mesh_Draw(0, 4, 2, polygonelements);
771 c_bloomdrawpixels += bloomwidth * bloomheight;
772 // render multiple times with a multiply blendfunc to raise to a power
773 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
774 for (x = 1;x < r_bloom_power.integer;x++)
776 R_Mesh_Draw(0, 4, 2, polygonelements);
778 c_bloomdrawpixels += bloomwidth * bloomheight;
780 // we now have a darkened bloom image in the framebuffer, copy it into
781 // the bloom image texture for more processing
782 memset(&m, 0, sizeof(m));
783 m.pointer_vertex = varray_vertex3f;
784 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
785 m.pointer_texcoord[0] = varray_texcoord2f[2];
788 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
790 c_bloomcopypixels += bloomwidth * bloomheight;
791 // blend on at multiple vertical offsets to achieve a vertical blur
792 // TODO: do offset blends using GLSL
793 range = r_bloom_blur.integer * bloomwidth / 320;
794 GL_BlendFunc(GL_ONE, GL_ZERO);
795 for (x = -range;x <= range;x++)
797 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
798 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
799 // compute a texcoord array with the specified x and y offset
800 varray_texcoord2f[2][0] = xoffset+0;
801 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
802 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
803 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
804 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
805 varray_texcoord2f[2][5] = yoffset+0;
806 varray_texcoord2f[2][6] = xoffset+0;
807 varray_texcoord2f[2][7] = yoffset+0;
808 // this r value looks like a 'dot' particle, fading sharply to
809 // black at the edges
810 // (probably not realistic but looks good enough)
811 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
814 GL_Color(r, r, r, 1);
815 R_Mesh_Draw(0, 4, 2, polygonelements);
817 c_bloomdrawpixels += bloomwidth * bloomheight;
818 GL_BlendFunc(GL_ONE, GL_ONE);
820 // copy the vertically blurred bloom view to a texture
822 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
824 c_bloomcopypixels += bloomwidth * bloomheight;
825 // blend the vertically blurred image at multiple offsets horizontally
826 // to finish the blur effect
827 // TODO: do offset blends using GLSL
828 range = r_bloom_blur.integer * bloomwidth / 320;
829 GL_BlendFunc(GL_ONE, GL_ZERO);
830 for (x = -range;x <= range;x++)
832 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
833 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
834 // compute a texcoord array with the specified x and y offset
835 varray_texcoord2f[2][0] = xoffset+0;
836 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
837 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
838 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
839 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
840 varray_texcoord2f[2][5] = yoffset+0;
841 varray_texcoord2f[2][6] = xoffset+0;
842 varray_texcoord2f[2][7] = yoffset+0;
843 // this r value looks like a 'dot' particle, fading sharply to
844 // black at the edges
845 // (probably not realistic but looks good enough)
846 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
849 GL_Color(r, r, r, 1);
850 R_Mesh_Draw(0, 4, 2, polygonelements);
852 c_bloomdrawpixels += bloomwidth * bloomheight;
853 GL_BlendFunc(GL_ONE, GL_ONE);
855 // copy the blurred bloom view to a texture
857 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
859 c_bloomcopypixels += bloomwidth * bloomheight;
860 // go back to full view area
861 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
862 // put the original screen image back in place and blend the bloom
864 memset(&m, 0, sizeof(m));
865 m.pointer_vertex = varray_vertex3f;
866 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
867 m.pointer_texcoord[0] = varray_texcoord2f[0];
869 dobloomblend = false;
871 // do both in one pass if possible
872 if (r_textureunits.integer >= 2 && gl_combine.integer)
874 dobloomblend = false;
875 m.texcombinergb[1] = GL_ADD;
876 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
877 m.pointer_texcoord[1] = varray_texcoord2f[1];
883 GL_BlendFunc(GL_ONE, GL_ZERO);
885 R_Mesh_Draw(0, 4, 2, polygonelements);
887 c_bloomdrawpixels += r_view_width * r_view_height;
888 // now blend on the bloom texture if multipass
891 memset(&m, 0, sizeof(m));
892 m.pointer_vertex = varray_vertex3f;
893 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
894 m.pointer_texcoord[0] = varray_texcoord2f[1];
896 GL_BlendFunc(GL_ONE, GL_ONE);
898 R_Mesh_Draw(0, 4, 2, polygonelements);
900 c_bloomdrawpixels += r_view_width * r_view_height;
903 if (r_refdef.viewblend[3] >= 0.01f)
905 // apply a color tint to the whole view
906 memset(&m, 0, sizeof(m));
907 m.pointer_vertex = varray_vertex3f;
909 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
910 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
911 R_Mesh_Draw(0, 4, 2, polygonelements);
915 void R_RenderScene(void);
917 matrix4x4_t r_waterscrollmatrix;
924 void R_RenderView(void)
926 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
927 return; //Host_Error ("R_RenderView: NULL worldmodel");
929 r_view_width = bound(0, r_refdef.width, vid.width);
930 r_view_height = bound(0, r_refdef.height, vid.height);
932 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
933 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
935 r_view_fov_x = bound(1, r_refdef.fov_x, 170);
936 r_view_fov_y = bound(1, r_refdef.fov_y, 170);
937 r_view_matrix = r_refdef.viewentitymatrix;
938 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
939 r_rtworld = r_shadow_realtime_world.integer;
940 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
941 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
942 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
943 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
945 // GL is weird because it's bottom to top, r_view_y is top to bottom
946 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
947 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
948 GL_ScissorTest(true);
954 R_TimeReport("setup");
956 qglDepthFunc(GL_LEQUAL);
957 qglPolygonOffset(0, 0);
958 qglEnable(GL_POLYGON_OFFSET_FILL);
962 qglPolygonOffset(0, 0);
963 qglDisable(GL_POLYGON_OFFSET_FILL);
966 R_TimeReport("blendview");
968 GL_Scissor(0, 0, vid.width, vid.height);
969 GL_ScissorTest(false);
972 extern void R_DrawLightningBeams (void);
973 void R_RenderScene(void)
975 // don't let sound skip if going slow
976 if (r_refdef.extraupdate)
981 R_MeshQueue_BeginScene();
983 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
987 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
988 if (r_rtworldshadows || r_rtdlightshadows)
989 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
991 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
993 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
995 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);
1000 R_TimeReport("worldvis");
1003 R_TimeReport("markentity");
1005 R_Shadow_UpdateWorldLightSelection();
1007 // don't let sound skip if going slow
1008 if (r_refdef.extraupdate)
1011 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1012 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1014 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1015 R_TimeReport("worldsky");
1018 if (R_DrawBrushModelsSky())
1019 R_TimeReport("bmodelsky");
1021 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1022 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1024 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1025 R_TimeReport("world");
1028 // don't let sound skip if going slow
1029 if (r_refdef.extraupdate)
1032 GL_ShowTrisColor(0, 0.015, 0, 1);
1035 R_TimeReport("models");
1037 // don't let sound skip if going slow
1038 if (r_refdef.extraupdate)
1041 GL_ShowTrisColor(0, 0, 0.033, 1);
1042 R_ShadowVolumeLighting(false);
1043 R_TimeReport("rtlights");
1045 // don't let sound skip if going slow
1046 if (r_refdef.extraupdate)
1049 GL_ShowTrisColor(0.1, 0, 0, 1);
1051 R_DrawLightningBeams();
1052 R_TimeReport("lightning");
1055 R_TimeReport("particles");
1058 R_TimeReport("explosions");
1060 R_MeshQueue_RenderTransparent();
1061 R_TimeReport("drawtrans");
1064 R_TimeReport("coronas");
1066 R_DrawWorldCrosshair();
1067 R_TimeReport("crosshair");
1069 R_MeshQueue_Render();
1070 R_MeshQueue_EndScene();
1072 if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1074 R_ShadowVolumeLighting(true);
1075 R_TimeReport("visiblevolume");
1078 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1080 // don't let sound skip if going slow
1081 if (r_refdef.extraupdate)
1086 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1089 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1091 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1092 GL_DepthMask(false);
1094 R_Mesh_Matrix(&r_identitymatrix);
1096 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1097 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1098 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1099 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1100 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1101 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1102 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1103 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1104 R_FillColors(color, 8, cr, cg, cb, ca);
1107 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1109 VectorSubtract(v, r_vieworigin, diff);
1110 f2 = exp(fogdensity/DotProduct(diff, diff));
1112 c[0] = c[0] * f1 + fogcolor[0] * f2;
1113 c[1] = c[1] * f1 + fogcolor[1] * f2;
1114 c[2] = c[2] * f1 + fogcolor[2] * f2;
1117 memset(&m, 0, sizeof(m));
1118 m.pointer_vertex = vertex3f;
1119 m.pointer_color = color;
1125 int nomodelelements[24] =
1137 float nomodelvertex3f[6*3] =
1147 float nomodelcolor4f[6*4] =
1149 0.0f, 0.0f, 0.5f, 1.0f,
1150 0.0f, 0.0f, 0.5f, 1.0f,
1151 0.0f, 0.5f, 0.0f, 1.0f,
1152 0.0f, 0.5f, 0.0f, 1.0f,
1153 0.5f, 0.0f, 0.0f, 1.0f,
1154 0.5f, 0.0f, 0.0f, 1.0f
1157 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1159 const entity_render_t *ent = (entity_render_t *)calldata1;
1161 float f1, f2, *c, diff[3];
1164 R_Mesh_Matrix(&ent->matrix);
1166 memset(&m, 0, sizeof(m));
1167 m.pointer_vertex = nomodelvertex3f;
1169 if (ent->flags & EF_ADDITIVE)
1171 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1172 GL_DepthMask(false);
1174 else if (ent->alpha < 1)
1176 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1177 GL_DepthMask(false);
1181 GL_BlendFunc(GL_ONE, GL_ZERO);
1184 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1187 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1188 m.pointer_color = color4f;
1189 VectorSubtract(ent->origin, r_vieworigin, diff);
1190 f2 = exp(fogdensity/DotProduct(diff, diff));
1192 for (i = 0, c = color4f;i < 6;i++, c += 4)
1194 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1195 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1196 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1200 else if (ent->alpha != 1)
1202 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1203 m.pointer_color = color4f;
1204 for (i = 0, c = color4f;i < 6;i++, c += 4)
1208 m.pointer_color = nomodelcolor4f;
1210 R_Mesh_Draw(0, 6, 8, nomodelelements);
1213 void R_DrawNoModel(entity_render_t *ent)
1215 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1216 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1218 // R_DrawNoModelCallback(ent, 0);
1221 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1223 vec3_t right1, right2, diff, normal;
1225 VectorSubtract (org2, org1, normal);
1227 // calculate 'right' vector for start
1228 VectorSubtract (r_vieworigin, org1, diff);
1229 CrossProduct (normal, diff, right1);
1230 VectorNormalize (right1);
1232 // calculate 'right' vector for end
1233 VectorSubtract (r_vieworigin, org2, diff);
1234 CrossProduct (normal, diff, right2);
1235 VectorNormalize (right2);
1237 vert[ 0] = org1[0] + width * right1[0];
1238 vert[ 1] = org1[1] + width * right1[1];
1239 vert[ 2] = org1[2] + width * right1[2];
1240 vert[ 3] = org1[0] - width * right1[0];
1241 vert[ 4] = org1[1] - width * right1[1];
1242 vert[ 5] = org1[2] - width * right1[2];
1243 vert[ 6] = org2[0] - width * right2[0];
1244 vert[ 7] = org2[1] - width * right2[1];
1245 vert[ 8] = org2[2] - width * right2[2];
1246 vert[ 9] = org2[0] + width * right2[0];
1247 vert[10] = org2[1] + width * right2[1];
1248 vert[11] = org2[2] + width * right2[2];
1251 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1253 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)
1260 VectorSubtract(origin, r_vieworigin, diff);
1261 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1264 R_Mesh_Matrix(&r_identitymatrix);
1265 GL_BlendFunc(blendfunc1, blendfunc2);
1266 GL_DepthMask(false);
1267 GL_DepthTest(!depthdisable);
1269 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1270 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1271 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1272 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1273 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1274 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1275 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1276 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1277 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1278 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1279 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1280 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1282 memset(&m, 0, sizeof(m));
1283 m.tex[0] = R_GetTexture(texture);
1284 m.pointer_texcoord[0] = spritetexcoord2f;
1285 m.pointer_vertex = varray_vertex3f;
1287 GL_Color(cr, cg, cb, ca);
1288 R_Mesh_Draw(0, 4, 2, polygonelements);
1291 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1295 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1296 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1298 if (i == mesh->numvertices)
1300 if (mesh->numvertices < mesh->maxvertices)
1302 VectorCopy(v, vertex3f);
1303 mesh->numvertices++;
1305 return mesh->numvertices;
1311 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1315 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1316 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1317 e = mesh->element3i + mesh->numtriangles * 3;
1318 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1320 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1321 if (mesh->numtriangles < mesh->maxtriangles)
1326 mesh->numtriangles++;
1328 element[1] = element[2];
1332 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1334 int planenum, planenum2;
1337 mplane_t *plane, *plane2;
1338 float temppoints[2][256*3];
1339 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1343 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1344 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1346 if (planenum2 == planenum)
1348 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);
1351 if (tempnumpoints < 3)
1353 // generate elements forming a triangle fan for this polygon
1354 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1358 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)
1360 texturelayer_t *layer;
1361 layer = t->currentlayers + t->currentnumlayers++;
1363 layer->depthmask = depthmask;
1364 layer->blendfunc1 = blendfunc1;
1365 layer->blendfunc2 = blendfunc2;
1366 layer->texture = texture;
1367 layer->texmatrix = *matrix;
1368 layer->color[0] = r;
1369 layer->color[1] = g;
1370 layer->color[2] = b;
1371 layer->color[3] = a;
1374 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1376 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1377 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1381 texture_t *texture = t;
1382 model_t *model = ent->model;
1383 int s = ent->skinnum;
1384 if ((unsigned int)s >= (unsigned int)model->numskins)
1388 if (model->skinscenes)
1390 if (model->skinscenes[s].framecount > 1)
1391 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1393 s = model->skinscenes[s].firstframe;
1396 t = t + s * model->num_surfaces;
1398 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];
1399 texture->currentframe = t;
1402 t->currentmaterialflags = t->basematerialflags;
1403 currentalpha = ent->alpha;
1404 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1405 currentalpha *= r_wateralpha.value;
1406 if (!(ent->flags & RENDER_LIGHT))
1407 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1408 if (ent->effects & EF_ADDITIVE)
1409 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1410 else if (currentalpha < 1)
1411 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1412 if (ent->effects & EF_NODEPTHTEST)
1413 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1414 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1415 t->currenttexmatrix = r_waterscrollmatrix;
1417 t->currenttexmatrix = r_identitymatrix;
1418 t->currentnumlayers = 0;
1419 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1421 if (gl_lightmaps.integer)
1422 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1423 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1425 // transparent sky would be ridiculous
1426 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1427 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1431 int blendfunc1, blendfunc2, depthmask;
1432 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1434 blendfunc1 = GL_SRC_ALPHA;
1435 blendfunc2 = GL_ONE;
1438 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1440 blendfunc1 = GL_SRC_ALPHA;
1441 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1446 blendfunc1 = GL_ONE;
1447 blendfunc2 = GL_ZERO;
1450 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1452 rtexture_t *currentbasetexture;
1454 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1455 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1456 currentbasetexture = (ent->colormap < 0 && t->skin.merged) ? t->skin.merged : t->skin.base;
1457 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1459 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], currentalpha);
1460 if (ent->colormap >= 0 && t->skin.pants)
1461 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);
1462 if (ent->colormap >= 0 && t->skin.shirt)
1463 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);
1469 // q3bsp has no lightmap updates, so the lightstylevalue that
1470 // would normally be baked into the lightmaptexture must be
1471 // applied to the color
1472 if (ent->model->type == mod_brushq3)
1473 colorscale *= d_lightstylevalue[0] * (1.0f / 256.0f);
1474 // transparent and fullbright are not affected by r_lightmapintensity
1475 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1476 colorscale *= r_lightmapintensity;
1477 if (r_textureunits.integer >= 2 && gl_combine.integer)
1478 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);
1479 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1480 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);
1482 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);
1483 if (r_ambient.value >= (1.0f/64.0f))
1484 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);
1485 if (ent->colormap >= 0 && t->skin.pants)
1487 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);
1488 if (r_ambient.value >= (1.0f/64.0f))
1489 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);
1491 if (ent->colormap >= 0 && t->skin.shirt)
1493 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);
1494 if (r_ambient.value >= (1.0f/64.0f))
1495 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);
1498 if (t->skin.glow != NULL)
1499 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, currentalpha);
1500 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1502 // if this is opaque use alpha blend which will darken the earlier
1505 // if this is an alpha blended material, all the earlier passes
1506 // were darkened by fog already, so we only need to add the fog
1507 // color ontop through the fog mask texture
1509 // if this is an additive blended material, all the earlier passes
1510 // were darkened by fog already, and we should not add fog color
1511 // (because the background was not darkened, there is no fog color
1512 // that was lost behind it).
1513 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);
1520 void R_UpdateAllTextureInfo(entity_render_t *ent)
1524 for (i = 0;i < ent->model->num_textures;i++)
1525 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1528 float *rsurface_vertex3f;
1529 float *rsurface_svector3f;
1530 float *rsurface_tvector3f;
1531 float *rsurface_normal3f;
1532 float *rsurface_lightmapcolor4f;
1534 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1537 float center[3], forward[3], right[3], up[3], v[4][3];
1538 matrix4x4_t matrix1, imatrix1;
1539 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1541 rsurface_vertex3f = varray_vertex3f;
1542 rsurface_svector3f = NULL;
1543 rsurface_tvector3f = NULL;
1544 rsurface_normal3f = NULL;
1545 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1549 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1550 rsurface_svector3f = surface->groupmesh->data_svector3f;
1551 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1552 rsurface_normal3f = surface->groupmesh->data_normal3f;
1554 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1556 if (!rsurface_svector3f)
1558 rsurface_svector3f = varray_svector3f;
1559 rsurface_tvector3f = varray_tvector3f;
1560 rsurface_normal3f = varray_normal3f;
1561 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);
1563 // a single autosprite surface can contain multiple sprites...
1564 VectorClear(forward);
1566 VectorSet(up, 0, 0, 1);
1567 for (j = 0;j < surface->num_vertices - 3;j += 4)
1569 VectorClear(center);
1570 for (i = 0;i < 4;i++)
1571 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1572 VectorScale(center, 0.25f, center);
1573 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1574 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);
1575 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1576 for (i = 0;i < 4;i++)
1577 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1578 forward[0] = modelorg[0] - center[0];
1579 forward[1] = modelorg[1] - center[1];
1580 VectorNormalize(forward);
1581 right[0] = forward[1];
1582 right[1] = -forward[0];
1583 for (i = 0;i < 4;i++)
1584 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1586 rsurface_vertex3f = varray_vertex3f;
1587 rsurface_svector3f = NULL;
1588 rsurface_tvector3f = NULL;
1589 rsurface_normal3f = NULL;
1591 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1593 if (!rsurface_svector3f)
1595 rsurface_svector3f = varray_svector3f;
1596 rsurface_tvector3f = varray_tvector3f;
1597 rsurface_normal3f = varray_normal3f;
1598 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);
1600 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1601 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1602 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1603 // a single autosprite surface can contain multiple sprites...
1604 for (j = 0;j < surface->num_vertices - 3;j += 4)
1606 VectorClear(center);
1607 for (i = 0;i < 4;i++)
1608 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1609 VectorScale(center, 0.25f, center);
1610 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1611 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);
1612 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1613 for (i = 0;i < 4;i++)
1614 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1615 for (i = 0;i < 4;i++)
1616 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1618 rsurface_vertex3f = varray_vertex3f;
1619 rsurface_svector3f = NULL;
1620 rsurface_tvector3f = NULL;
1621 rsurface_normal3f = NULL;
1623 R_Mesh_VertexPointer(rsurface_vertex3f);
1626 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)
1635 vec4_t ambientcolor4f;
1636 vec3_t diffusecolor;
1637 vec3_t diffusenormal;
1638 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1640 rsurface_lightmapcolor4f = varray_color4f;
1641 if (rsurface_normal3f == NULL)
1643 rsurface_normal3f = varray_normal3f;
1644 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);
1646 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);
1655 r = ambientcolor4f[0];
1656 g = ambientcolor4f[1];
1657 b = ambientcolor4f[2];
1658 a = ambientcolor4f[3];
1659 rsurface_lightmapcolor4f = NULL;
1662 else if (lightmode >= 1)
1664 if (surface->lightmapinfo)
1666 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1668 const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1671 float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1672 VectorScale(lm, scale, c);
1673 if (surface->lightmapinfo->styles[1] != 255)
1675 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1677 scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1678 VectorMA(c, scale, lm, c);
1679 if (surface->lightmapinfo->styles[2] != 255)
1682 scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1683 VectorMA(c, scale, lm, c);
1684 if (surface->lightmapinfo->styles[3] != 255)
1687 scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1688 VectorMA(c, scale, lm, c);
1696 rsurface_lightmapcolor4f = varray_color4f;
1699 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1702 rsurface_lightmapcolor4f = NULL;
1705 if (rsurface_lightmapcolor4f)
1707 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)
1709 VectorSubtract(v, modelorg, diff);
1710 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1719 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)
1721 VectorSubtract(v, modelorg, diff);
1722 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1729 rsurface_lightmapcolor4f = varray_color4f;
1731 if (applycolor && rsurface_lightmapcolor4f)
1733 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)
1740 rsurface_lightmapcolor4f = varray_color4f;
1742 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1743 GL_Color(r, g, b, a);
1747 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1749 int texturesurfaceindex;
1751 const msurface_t *surface;
1752 qboolean applycolor;
1754 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1756 c_faces += texturenumsurfaces;
1757 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1758 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1759 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1760 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1761 qglDisable(GL_CULL_FACE);
1762 if (texture->currentnumlayers)
1765 texturelayer_t *layer;
1766 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1769 int layertexrgbscale;
1770 GL_DepthMask(layer->depthmask);
1771 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1772 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1774 layertexrgbscale = 4;
1775 VectorScale(layer->color, 0.25f, layercolor);
1777 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
1779 layertexrgbscale = 2;
1780 VectorScale(layer->color, 0.5f, layercolor);
1784 layertexrgbscale = 1;
1785 VectorScale(layer->color, 1.0f, layercolor);
1787 layercolor[3] = layer->color[3];
1788 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1789 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
1790 switch (layer->type)
1792 case TEXTURELAYERTYPE_SKY:
1795 skyrendernow = false;
1796 if (skyrendermasked)
1799 // restore entity matrix and GL_Color
1800 R_Mesh_Matrix(&ent->matrix);
1801 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1804 // LordHavoc: HalfLife maps have freaky skypolys...
1805 //if (!ent->model->brush.ishlbsp)
1807 if (skyrendermasked)
1809 // depth-only (masking)
1810 GL_ColorMask(0,0,0,0);
1811 // just to make sure that braindead drivers don't draw anything
1812 // despite that colormask...
1813 GL_BlendFunc(GL_ZERO, GL_ONE);
1818 GL_BlendFunc(GL_ONE, GL_ZERO);
1820 memset(&m, 0, sizeof(m));
1822 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1824 surface = texturesurfacelist[texturesurfaceindex];
1825 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1826 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1827 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1828 GL_LockArrays(0, 0);
1830 if (skyrendermasked)
1831 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1834 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
1835 memset(&m, 0, sizeof(m));
1836 m.tex[1] = R_GetTexture(layer->texture);
1837 m.texmatrix[1] = layer->texmatrix;
1838 m.texrgbscale[1] = layertexrgbscale;
1839 m.pointer_color = varray_color4f;
1841 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1843 surface = texturesurfacelist[texturesurfaceindex];
1844 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1845 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1846 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1849 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1850 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1852 else if (surface->lightmaptexture)
1854 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1855 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1859 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1860 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1862 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1863 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1864 GL_LockArrays(0, 0);
1867 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
1868 memset(&m, 0, sizeof(m));
1869 m.tex[0] = R_GetTexture(layer->texture);
1870 m.texmatrix[0] = layer->texmatrix;
1871 m.pointer_color = varray_color4f;
1872 m.texrgbscale[0] = layertexrgbscale;
1874 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1876 surface = texturesurfacelist[texturesurfaceindex];
1877 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1878 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1881 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1882 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
1884 else if (surface->lightmaptexture)
1886 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1887 R_Mesh_ColorPointer(NULL);
1891 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1892 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
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);
1898 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1899 memset(&m, 0, sizeof(m));
1900 m.tex[0] = R_GetTexture(layer->texture);
1901 m.texmatrix[0] = layer->texmatrix;
1902 m.pointer_color = varray_color4f;
1903 m.texrgbscale[0] = layertexrgbscale;
1905 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1907 surface = texturesurfacelist[texturesurfaceindex];
1908 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1909 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1910 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1911 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1912 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1913 GL_LockArrays(0, 0);
1916 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
1917 memset(&m, 0, sizeof(m));
1918 m.tex[0] = R_GetTexture(layer->texture);
1919 m.texmatrix[0] = layer->texmatrix;
1920 m.texrgbscale[0] = layertexrgbscale;
1921 m.pointer_color = varray_color4f;
1923 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1925 surface = texturesurfacelist[texturesurfaceindex];
1926 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1927 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1928 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1929 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1930 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1931 GL_LockArrays(0, 0);
1934 case TEXTURELAYERTYPE_TEXTURE:
1935 memset(&m, 0, sizeof(m));
1936 m.tex[0] = R_GetTexture(layer->texture);
1937 m.texmatrix[0] = layer->texmatrix;
1938 m.pointer_color = varray_color4f;
1939 m.texrgbscale[0] = layertexrgbscale;
1941 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1943 surface = texturesurfacelist[texturesurfaceindex];
1944 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1945 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1946 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1947 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1948 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1949 GL_LockArrays(0, 0);
1952 case TEXTURELAYERTYPE_FOG:
1953 memset(&m, 0, sizeof(m));
1956 m.tex[0] = R_GetTexture(layer->texture);
1957 m.texmatrix[0] = layer->texmatrix;
1960 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1965 surface = texturesurfacelist[texturesurfaceindex];
1966 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1968 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1969 R_Mesh_ColorPointer(varray_color4f);
1970 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)
1972 VectorSubtract(v, modelorg, diff);
1973 f = exp(fogdensity/DotProduct(diff, diff));
1974 c[0] = layercolor[0];
1975 c[1] = layercolor[1];
1976 c[2] = layercolor[2];
1977 c[3] = f * layercolor[3];
1979 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1980 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1981 GL_LockArrays(0, 0);
1985 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
1987 // if trying to do overbright on first pass of an opaque surface
1988 // when combine is not supported, brighten as a post process
1989 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
1992 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1993 GL_Color(1, 1, 1, 1);
1994 memset(&m, 0, sizeof(m));
1996 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1998 surface = texturesurfacelist[texturesurfaceindex];
1999 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2000 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2001 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2002 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2003 GL_LockArrays(0, 0);
2008 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2009 qglEnable(GL_CULL_FACE);
2012 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2014 const entity_render_t *ent = (entity_render_t *)calldata1;
2015 const msurface_t *surface = ent->model->data_surfaces + calldata2;
2019 texture = surface->texture;
2020 if (texture->basematerialflags & MATERIALFLAG_SKY)
2021 return; // transparent sky is too difficult
2022 R_UpdateTextureInfo(ent, texture);
2024 R_Mesh_Matrix(&ent->matrix);
2025 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2026 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2029 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2031 int texturesurfaceindex;
2032 const msurface_t *surface;
2033 vec3_t tempcenter, center;
2034 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2036 // drawing sky transparently would be too difficult
2037 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2039 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2041 surface = texturesurfacelist[texturesurfaceindex];
2042 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2043 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2044 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2045 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2046 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2051 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2054 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2055 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2057 int i, j, f, flagsmask;
2058 msurface_t *surface, **surfacechain;
2059 texture_t *t, *texture;
2060 model_t *model = ent->model;
2062 const int maxsurfacelist = 1024;
2063 int numsurfacelist = 0;
2064 const msurface_t *surfacelist[1024];
2067 R_Mesh_Matrix(&ent->matrix);
2068 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2070 // update light styles
2071 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2073 for (i = 0;i < model->brushq1.light_styles;i++)
2075 if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
2077 model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
2078 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2079 for (;(surface = *surfacechain);surfacechain++)
2080 surface->cached_dlight = true;
2085 R_UpdateAllTextureInfo(ent);
2086 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2091 if (ent == r_refdef.worldentity)
2093 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2095 if (!r_worldsurfacevisible[j])
2097 if (t != surface->texture)
2101 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2104 t = surface->texture;
2105 texture = t->currentframe;
2106 f = texture->currentmaterialflags & flagsmask;
2108 if (f && surface->num_triangles)
2110 // if lightmap parameters changed, rebuild lightmap texture
2111 if (surface->cached_dlight && surface->lightmapinfo->samples)
2112 R_BuildLightMap(ent, surface);
2113 // add face to draw list
2114 surfacelist[numsurfacelist++] = surface;
2115 if (numsurfacelist >= maxsurfacelist)
2117 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2125 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2127 if (t != surface->texture)
2131 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2134 t = surface->texture;
2135 texture = t->currentframe;
2136 f = texture->currentmaterialflags & flagsmask;
2138 if (f && surface->num_triangles)
2140 // if lightmap parameters changed, rebuild lightmap texture
2141 if (surface->cached_dlight && surface->lightmapinfo->samples)
2142 R_BuildLightMap(ent, surface);
2143 // add face to draw list
2144 surfacelist[numsurfacelist++] = surface;
2145 if (numsurfacelist >= maxsurfacelist)
2147 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2154 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);