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"};
100 cvar_t r_watershader = {CVAR_SAVE, "r_watershader", "1"};
102 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0"};
103 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "2"};
104 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "8"};
105 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
106 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"};
108 cvar_t developer_texturelogging = {0, "developer_texturelogging", "1"};
110 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
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;
121 rtexture_t *r_texture_detailtextures[NUM_DETAILTEXTURES];
122 rtexture_t *r_texture_distorttexture[64];
124 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
127 for (i = 0;i < verts;i++)
138 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
141 for (i = 0;i < verts;i++)
153 float fog_density, fog_red, fog_green, fog_blue;
155 qboolean oldgl_fogenable;
156 void R_UpdateFog(void)
158 if (gamemode == GAME_NEHAHRA)
160 if (gl_fogenable.integer)
162 oldgl_fogenable = true;
163 fog_density = gl_fogdensity.value;
164 fog_red = gl_fogred.value;
165 fog_green = gl_foggreen.value;
166 fog_blue = gl_fogblue.value;
168 else if (oldgl_fogenable)
170 oldgl_fogenable = false;
179 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
180 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
181 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
186 fogdensity = -4000.0f / (fog_density * fog_density);
187 // fog color was already set
193 // FIXME: move this to client?
196 if (gamemode == GAME_NEHAHRA)
198 Cvar_Set("gl_fogenable", "0");
199 Cvar_Set("gl_fogdensity", "0.2");
200 Cvar_Set("gl_fogred", "0.3");
201 Cvar_Set("gl_foggreen", "0.3");
202 Cvar_Set("gl_fogblue", "0.3");
204 fog_density = fog_red = fog_green = fog_blue = 0.0f;
207 // FIXME: move this to client?
208 void FOG_registercvars(void)
210 if (gamemode == GAME_NEHAHRA)
212 Cvar_RegisterVariable (&gl_fogenable);
213 Cvar_RegisterVariable (&gl_fogdensity);
214 Cvar_RegisterVariable (&gl_fogred);
215 Cvar_RegisterVariable (&gl_foggreen);
216 Cvar_RegisterVariable (&gl_fogblue);
217 Cvar_RegisterVariable (&gl_fogstart);
218 Cvar_RegisterVariable (&gl_fogend);
222 static void R_BuildDetailTextures (void)
225 float vc[3], vx[3], vy[3], vn[3], lightdir[3];
226 #define DETAILRESOLUTION 256
227 qbyte (*data)[DETAILRESOLUTION][4];
228 qbyte (*noise)[DETAILRESOLUTION];
230 // Allocate the buffers dynamically to avoid having such big guys on the stack
231 data = Mem_Alloc(tempmempool, DETAILRESOLUTION * sizeof(*data));
232 noise = Mem_Alloc(tempmempool, DETAILRESOLUTION * sizeof(*noise));
237 VectorNormalize(lightdir);
238 for (i = 0;i < NUM_DETAILTEXTURES;i++)
240 fractalnoise(&noise[0][0], DETAILRESOLUTION, DETAILRESOLUTION >> 4);
241 for (y = 0;y < DETAILRESOLUTION;y++)
243 for (x = 0;x < DETAILRESOLUTION;x++)
247 vc[2] = noise[y][x] * (1.0f / 32.0f);
250 vx[2] = noise[y][(x + 1) % DETAILRESOLUTION] * (1.0f / 32.0f);
253 vy[2] = noise[(y + 1) % DETAILRESOLUTION][x] * (1.0f / 32.0f);
254 VectorSubtract(vx, vc, vx);
255 VectorSubtract(vy, vc, vy);
256 CrossProduct(vx, vy, vn);
258 light = 128 - DotProduct(vn, lightdir) * 128;
259 light = bound(0, light, 255);
260 data[y][x][0] = data[y][x][1] = data[y][x][2] = light;
264 r_texture_detailtextures[i] = R_LoadTexture2D(r_main_texturepool, va("detailtexture%i", i), DETAILRESOLUTION, DETAILRESOLUTION, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_PRECACHE, NULL);
271 static qbyte R_MorphDistortTexture (double y0, double y1, double y2, double y3, double morph)
273 int m = (int)(((y1 + y3 - (y0 + y2)) * morph * morph * morph) +
274 ((2 * (y0 - y1) + y2 - y3) * morph * morph) +
275 ((y2 - y0) * morph) +
277 return (qbyte)bound(0, m, 255);
280 static void R_BuildDistortTexture (void)
283 #define DISTORTRESOLUTION 32
284 qbyte data[5][DISTORTRESOLUTION][DISTORTRESOLUTION][2];
288 for (y=0; y<DISTORTRESOLUTION; y++)
290 for (x=0; x<DISTORTRESOLUTION; x++)
292 data[i][y][x][0] = rand () & 255;
293 data[i][y][x][1] = rand () & 255;
302 r_texture_distorttexture[i*16+j] = NULL;
303 if (gl_textureshader)
305 for (y=0; y<DISTORTRESOLUTION; y++)
307 for (x=0; x<DISTORTRESOLUTION; x++)
309 data[4][y][x][0] = R_MorphDistortTexture (data[(i-1)&3][y][x][0], data[i][y][x][0], data[(i+1)&3][y][x][0], data[(i+2)&3][y][x][0], 0.0625*j);
310 data[4][y][x][1] = R_MorphDistortTexture (data[(i-1)&3][y][x][1], data[i][y][x][1], data[(i+1)&3][y][x][1], data[(i+2)&3][y][x][1], 0.0625*j);
313 r_texture_distorttexture[i*16+j] = R_LoadTexture2D(r_main_texturepool, va("distorttexture%i", i*16+j), DISTORTRESOLUTION, DISTORTRESOLUTION, &data[4][0][0][0], TEXTYPE_DSDT, TEXF_PRECACHE, NULL);
319 static void R_BuildBlankTextures(void)
322 data[0] = 128; // normal X
323 data[1] = 128; // normal Y
324 data[2] = 255; // normal Z
325 data[3] = 128; // height
326 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
331 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
336 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
339 static void R_BuildNoTexture(void)
342 qbyte pix[16][16][4];
343 // this makes a light grey/dark grey checkerboard texture
344 for (y = 0;y < 16;y++)
346 for (x = 0;x < 16;x++)
348 if ((y < 8) ^ (x < 8))
364 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
367 static void R_BuildWhiteCube(void)
370 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
371 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
372 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
373 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
374 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
375 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
376 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
379 static void R_BuildNormalizationCube(void)
383 vec_t s, t, intensity;
385 qbyte data[6][NORMSIZE][NORMSIZE][4];
386 for (side = 0;side < 6;side++)
388 for (y = 0;y < NORMSIZE;y++)
390 for (x = 0;x < NORMSIZE;x++)
392 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
393 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
427 intensity = 127.0f / sqrt(DotProduct(v, v));
428 data[side][y][x][0] = 128.0f + intensity * v[0];
429 data[side][y][x][1] = 128.0f + intensity * v[1];
430 data[side][y][x][2] = 128.0f + intensity * v[2];
431 data[side][y][x][3] = 255;
435 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
438 void gl_main_start(void)
440 r_main_texturepool = R_AllocTexturePool();
441 r_bloom_texture_screen = NULL;
442 r_bloom_texture_bloom = NULL;
443 R_BuildBlankTextures();
445 R_BuildDetailTextures();
446 R_BuildDistortTexture();
447 if (gl_texturecubemap)
450 R_BuildNormalizationCube();
454 void gl_main_shutdown(void)
456 R_FreeTexturePool(&r_main_texturepool);
457 r_bloom_texture_screen = NULL;
458 r_bloom_texture_bloom = NULL;
459 r_texture_blanknormalmap = NULL;
460 r_texture_white = NULL;
461 r_texture_black = NULL;
462 r_texture_whitecube = NULL;
463 r_texture_normalizationcube = NULL;
466 extern void CL_ParseEntityLump(char *entitystring);
467 void gl_main_newmap(void)
469 // FIXME: move this code to client
471 char *entities, entname[MAX_QPATH];
475 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
476 l = strlen(entname) - 4;
477 if (l >= 0 && !strcmp(entname + l, ".bsp"))
479 strcpy(entname + l, ".ent");
480 if ((entities = FS_LoadFile(entname, tempmempool, true)))
482 CL_ParseEntityLump(entities);
487 if (cl.worldmodel->brush.entities)
488 CL_ParseEntityLump(cl.worldmodel->brush.entities);
492 void GL_Main_Init(void)
494 Matrix4x4_CreateIdentity(&r_identitymatrix);
495 // FIXME: move this to client?
497 Cvar_RegisterVariable(&r_showtris);
498 Cvar_RegisterVariable(&r_drawentities);
499 Cvar_RegisterVariable(&r_drawviewmodel);
500 Cvar_RegisterVariable(&r_speeds);
501 Cvar_RegisterVariable(&r_fullbrights);
502 Cvar_RegisterVariable(&r_wateralpha);
503 Cvar_RegisterVariable(&r_dynamic);
504 Cvar_RegisterVariable(&r_fullbright);
505 Cvar_RegisterVariable(&r_textureunits);
506 Cvar_RegisterVariable(&r_lerpsprites);
507 Cvar_RegisterVariable(&r_lerpmodels);
508 Cvar_RegisterVariable(&r_waterscroll);
509 Cvar_RegisterVariable(&r_watershader);
510 Cvar_RegisterVariable(&r_drawcollisionbrushes);
511 Cvar_RegisterVariable(&r_bloom);
512 Cvar_RegisterVariable(&r_bloom_intensity);
513 Cvar_RegisterVariable(&r_bloom_blur);
514 Cvar_RegisterVariable(&r_bloom_resolution);
515 Cvar_RegisterVariable(&r_bloom_power);
516 Cvar_RegisterVariable(&developer_texturelogging);
517 Cvar_RegisterVariable(&gl_lightmaps);
518 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
519 Cvar_SetValue("r_fullbrights", 0);
520 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
523 static vec3_t r_farclip_origin;
524 static vec3_t r_farclip_direction;
525 static vec_t r_farclip_directiondist;
526 static vec_t r_farclip_meshfarclip;
527 static int r_farclip_directionbit0;
528 static int r_farclip_directionbit1;
529 static int r_farclip_directionbit2;
531 // enlarge farclip to accomodate box
532 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
535 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
536 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
537 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
538 if (r_farclip_meshfarclip < d)
539 r_farclip_meshfarclip = d;
542 // return farclip value
543 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
547 VectorCopy(origin, r_farclip_origin);
548 VectorCopy(direction, r_farclip_direction);
549 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
550 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
551 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
552 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
553 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
555 if (r_refdef.worldmodel)
556 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
557 for (i = 0;i < r_refdef.numentities;i++)
558 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
560 return r_farclip_meshfarclip - r_farclip_directiondist;
563 extern void R_Textures_Init(void);
564 extern void GL_Draw_Init(void);
565 extern void GL_Main_Init(void);
566 extern void R_Shadow_Init(void);
567 extern void R_Sky_Init(void);
568 extern void GL_Surf_Init(void);
569 extern void R_Crosshairs_Init(void);
570 extern void R_Light_Init(void);
571 extern void R_Particles_Init(void);
572 extern void R_Explosion_Init(void);
573 extern void gl_backend_init(void);
574 extern void Sbar_Init(void);
575 extern void R_LightningBeams_Init(void);
576 extern void Mod_RenderInit(void);
578 void Render_Init(void)
595 R_LightningBeams_Init();
603 extern char *ENGINE_EXTENSIONS;
606 VID_CheckExtensions();
608 // LordHavoc: report supported extensions
609 Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
611 // clear to black (loading plaque will be seen over this)
612 qglClearColor(0,0,0,1);
613 qglClear(GL_COLOR_BUFFER_BIT);
616 int R_CullBox(const vec3_t mins, const vec3_t maxs)
620 for (i = 0;i < 4;i++)
627 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
631 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
635 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
639 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
643 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
647 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
651 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
655 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
663 //==================================================================================
665 static void R_MarkEntities (void)
668 entity_render_t *ent;
670 if (!r_drawentities.integer)
673 r_refdef.worldentity->visframe = r_framecount;
674 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
675 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
677 // worldmodel can check visibility
678 for (i = 0;i < r_refdef.numentities;i++)
680 ent = r_refdef.entities[i];
681 Mod_CheckLoaded(ent->model);
682 // some of the renderer still relies on origin...
683 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
684 // some of the renderer still relies on scale...
685 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
686 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)))
688 R_UpdateEntLights(ent);
689 ent->visframe = r_framecount;
695 // no worldmodel or it can't check visibility
696 for (i = 0;i < r_refdef.numentities;i++)
698 ent = r_refdef.entities[i];
699 Mod_CheckLoaded(ent->model);
700 // some of the renderer still relies on origin...
701 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
702 // some of the renderer still relies on scale...
703 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
704 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
706 R_UpdateEntLights(ent);
707 ent->visframe = r_framecount;
713 // only used if skyrendermasked, and normally returns false
714 int R_DrawBrushModelsSky (void)
717 entity_render_t *ent;
719 if (!r_drawentities.integer)
723 for (i = 0;i < r_refdef.numentities;i++)
725 ent = r_refdef.entities[i];
726 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
728 ent->model->DrawSky(ent);
735 void R_DrawNoModel(entity_render_t *ent);
736 void R_DrawModels(void)
739 entity_render_t *ent;
741 if (!r_drawentities.integer)
744 for (i = 0;i < r_refdef.numentities;i++)
746 ent = r_refdef.entities[i];
747 if (ent->visframe == r_framecount)
749 if (ent->model && ent->model->Draw != NULL)
750 ent->model->Draw(ent);
757 static void R_SetFrustum(void)
759 // break apart the view matrix into vectors for various purposes
760 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
761 VectorNegate(r_viewleft, r_viewright);
763 // LordHavoc: note to all quake engine coders, the special case for 90
764 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
767 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
768 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
769 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
770 PlaneClassify(&frustum[0]);
772 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
773 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
774 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
775 PlaneClassify(&frustum[1]);
777 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
778 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
779 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
780 PlaneClassify(&frustum[2]);
782 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
783 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
784 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
785 PlaneClassify(&frustum[3]);
788 VectorCopy(r_viewforward, frustum[4].normal);
789 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
790 PlaneClassify(&frustum[4]);
793 static void R_BlendView(void)
797 if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
800 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
803 R_Mesh_Matrix(&r_identitymatrix);
804 // vertex coordinates for a quad that covers the screen exactly
805 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
806 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
807 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
808 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
809 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)
811 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
812 float xoffset, yoffset, r;
814 // set the (poorly named) screenwidth and screenheight variables to
815 // a power of 2 at least as large as the screen, these will define the
816 // size of the texture to allocate
817 for (screenwidth = 1;screenwidth < vid.realwidth;screenwidth *= 2);
818 for (screenheight = 1;screenheight < vid.realheight;screenheight *= 2);
819 // allocate textures as needed
820 if (!r_bloom_texture_screen)
821 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
822 if (!r_bloom_texture_bloom)
823 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
824 // set bloomwidth and bloomheight to the bloom resolution that will be
825 // used (often less than the screen resolution for faster rendering)
826 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
827 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
828 // set up a texcoord array for the full resolution screen image
829 // (we have to keep this around to copy back during final render)
830 varray_texcoord2f[0][0] = 0;
831 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
832 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
833 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
834 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
835 varray_texcoord2f[0][5] = 0;
836 varray_texcoord2f[0][6] = 0;
837 varray_texcoord2f[0][7] = 0;
838 // set up a texcoord array for the reduced resolution bloom image
839 // (which will be additive blended over the screen image)
840 varray_texcoord2f[1][0] = 0;
841 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
842 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
843 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
844 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
845 varray_texcoord2f[1][5] = 0;
846 varray_texcoord2f[1][6] = 0;
847 varray_texcoord2f[1][7] = 0;
848 memset(&m, 0, sizeof(m));
849 m.pointer_vertex = varray_vertex3f;
850 m.pointer_texcoord[0] = varray_texcoord2f[0];
851 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
853 // copy view into the full resolution screen image texture
855 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
857 c_bloomcopypixels += r_view_width * r_view_height;
858 // now scale it down to the bloom size and raise to a power of itself
859 // to darken it (this leaves the really bright stuff bright, and
860 // everything else becomes very dark)
861 // TODO: optimize with multitexture or GLSL
862 qglViewport(r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
863 GL_BlendFunc(GL_ONE, GL_ZERO);
864 GL_Color(1, 1, 1, 1);
865 R_Mesh_Draw(0, 4, 2, polygonelements);
867 c_bloomdrawpixels += bloomwidth * bloomheight;
868 // render multiple times with a multiply blendfunc to raise to a power
869 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
870 for (x = 1;x < r_bloom_power.integer;x++)
872 R_Mesh_Draw(0, 4, 2, polygonelements);
874 c_bloomdrawpixels += bloomwidth * bloomheight;
876 // we now have a darkened bloom image in the framebuffer, copy it into
877 // the bloom image texture for more processing
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[2];
884 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
886 c_bloomcopypixels += bloomwidth * bloomheight;
887 // blend on at multiple vertical offsets to achieve a vertical blur
888 // TODO: do offset blends using GLSL
889 range = r_bloom_blur.integer * bloomwidth / 320;
890 GL_BlendFunc(GL_ONE, GL_ZERO);
891 for (x = -range;x <= range;x++)
893 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
894 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
895 // compute a texcoord array with the specified x and y offset
896 varray_texcoord2f[2][0] = xoffset+0;
897 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
898 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
899 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
900 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
901 varray_texcoord2f[2][5] = yoffset+0;
902 varray_texcoord2f[2][6] = xoffset+0;
903 varray_texcoord2f[2][7] = yoffset+0;
904 // this r value looks like a 'dot' particle, fading sharply to
905 // black at the edges
906 // (probably not realistic but looks good enough)
907 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
910 GL_Color(r, r, r, 1);
911 R_Mesh_Draw(0, 4, 2, polygonelements);
913 c_bloomdrawpixels += bloomwidth * bloomheight;
914 GL_BlendFunc(GL_ONE, GL_ONE);
916 // copy the vertically blurred bloom view to a texture
918 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
920 c_bloomcopypixels += bloomwidth * bloomheight;
921 // blend the vertically blurred image at multiple offsets horizontally
922 // to finish the blur effect
923 // TODO: do offset blends using GLSL
924 range = r_bloom_blur.integer * bloomwidth / 320;
925 GL_BlendFunc(GL_ONE, GL_ZERO);
926 for (x = -range;x <= range;x++)
928 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
929 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
930 // compute a texcoord array with the specified x and y offset
931 varray_texcoord2f[2][0] = xoffset+0;
932 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
933 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
934 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
935 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
936 varray_texcoord2f[2][5] = yoffset+0;
937 varray_texcoord2f[2][6] = xoffset+0;
938 varray_texcoord2f[2][7] = yoffset+0;
939 // this r value looks like a 'dot' particle, fading sharply to
940 // black at the edges
941 // (probably not realistic but looks good enough)
942 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
945 GL_Color(r, r, r, 1);
946 R_Mesh_Draw(0, 4, 2, polygonelements);
948 c_bloomdrawpixels += bloomwidth * bloomheight;
949 GL_BlendFunc(GL_ONE, GL_ONE);
951 // copy the blurred bloom view to a texture
953 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
955 c_bloomcopypixels += bloomwidth * bloomheight;
956 // go back to full view area
957 qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
958 // put the original screen image back in place and blend the bloom
960 memset(&m, 0, sizeof(m));
961 m.pointer_vertex = varray_vertex3f;
962 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
963 m.pointer_texcoord[0] = varray_texcoord2f[0];
965 dobloomblend = false;
967 // do both in one pass if possible
968 if (r_textureunits.integer >= 2 && gl_combine.integer)
970 dobloomblend = false;
971 m.texcombinergb[1] = GL_ADD;
972 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
973 m.pointer_texcoord[1] = varray_texcoord2f[1];
979 GL_BlendFunc(GL_ONE, GL_ZERO);
981 R_Mesh_Draw(0, 4, 2, polygonelements);
983 c_bloomdrawpixels += r_view_width * r_view_height;
984 // now blend on the bloom texture if multipass
987 memset(&m, 0, sizeof(m));
988 m.pointer_vertex = varray_vertex3f;
989 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
990 m.pointer_texcoord[0] = varray_texcoord2f[1];
992 GL_BlendFunc(GL_ONE, GL_ONE);
994 R_Mesh_Draw(0, 4, 2, polygonelements);
996 c_bloomdrawpixels += r_view_width * r_view_height;
999 if (r_refdef.viewblend[3] >= 0.01f)
1001 // apply a color tint to the whole view
1002 memset(&m, 0, sizeof(m));
1003 m.pointer_vertex = varray_vertex3f;
1005 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1006 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1007 R_Mesh_Draw(0, 4, 2, polygonelements);
1011 void R_RenderScene(void);
1013 matrix4x4_t r_waterscrollmatrix;
1020 void R_RenderView(void)
1022 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1023 return; //Host_Error ("R_RenderView: NULL worldmodel");
1025 r_view_width = bound(0, r_refdef.width, vid.realwidth);
1026 r_view_height = bound(0, r_refdef.height, vid.realheight);
1028 r_view_x = bound(0, r_refdef.x, vid.realwidth - r_refdef.width);
1029 r_view_y = bound(0, r_refdef.y, vid.realheight - r_refdef.height);
1031 r_view_fov_x = bound(1, r_refdef.fov_x, 170);
1032 r_view_fov_y = bound(1, r_refdef.fov_y, 170);
1033 r_view_matrix = r_refdef.viewentitymatrix;
1034 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1035 r_rtworld = r_shadow_realtime_world.integer;
1036 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1037 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1038 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1039 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1041 // GL is weird because it's bottom to top, r_view_y is top to bottom
1042 qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
1043 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1044 GL_ScissorTest(true);
1050 R_TimeReport("setup");
1052 qglDepthFunc(GL_LEQUAL);
1053 qglPolygonOffset(0, 0);
1054 qglEnable(GL_POLYGON_OFFSET_FILL);
1058 qglPolygonOffset(0, 0);
1059 qglDisable(GL_POLYGON_OFFSET_FILL);
1062 R_TimeReport("blendview");
1064 GL_Scissor(0, 0, vid.realwidth, vid.realheight);
1065 GL_ScissorTest(false);
1068 extern void R_DrawLightningBeams (void);
1069 void R_RenderScene(void)
1071 // don't let sound skip if going slow
1072 if (r_refdef.extraupdate)
1077 R_MeshQueue_BeginScene();
1079 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1083 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1084 if (r_rtworldshadows || r_rtdlightshadows)
1085 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
1087 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
1089 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1091 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);
1095 R_WorldVisibility();
1096 R_TimeReport("worldvis");
1099 R_TimeReport("markentity");
1101 R_Shadow_UpdateWorldLightSelection();
1103 // don't let sound skip if going slow
1104 if (r_refdef.extraupdate)
1107 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1108 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1110 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1111 R_TimeReport("worldsky");
1114 if (R_DrawBrushModelsSky())
1115 R_TimeReport("bmodelsky");
1117 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1118 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1120 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1121 R_TimeReport("world");
1124 // don't let sound skip if going slow
1125 if (r_refdef.extraupdate)
1128 GL_ShowTrisColor(0, 0.015, 0, 1);
1131 R_TimeReport("models");
1133 // don't let sound skip if going slow
1134 if (r_refdef.extraupdate)
1137 GL_ShowTrisColor(0, 0, 0.033, 1);
1138 R_ShadowVolumeLighting(false);
1139 R_TimeReport("rtlights");
1141 // don't let sound skip if going slow
1142 if (r_refdef.extraupdate)
1145 GL_ShowTrisColor(0.1, 0, 0, 1);
1147 R_DrawLightningBeams();
1148 R_TimeReport("lightning");
1151 R_TimeReport("particles");
1154 R_TimeReport("explosions");
1156 R_MeshQueue_RenderTransparent();
1157 R_TimeReport("drawtrans");
1160 R_TimeReport("coronas");
1162 R_DrawWorldCrosshair();
1163 R_TimeReport("crosshair");
1165 R_MeshQueue_Render();
1166 R_MeshQueue_EndScene();
1168 if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1170 R_ShadowVolumeLighting(true);
1171 R_TimeReport("visiblevolume");
1174 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1176 // don't let sound skip if going slow
1177 if (r_refdef.extraupdate)
1182 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1185 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1187 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1188 GL_DepthMask(false);
1190 R_Mesh_Matrix(&r_identitymatrix);
1192 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1193 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1194 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1195 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1196 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1197 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1198 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1199 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1200 R_FillColors(color, 8, cr, cg, cb, ca);
1203 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1205 VectorSubtract(v, r_vieworigin, diff);
1206 f2 = exp(fogdensity/DotProduct(diff, diff));
1208 c[0] = c[0] * f1 + fogcolor[0] * f2;
1209 c[1] = c[1] * f1 + fogcolor[1] * f2;
1210 c[2] = c[2] * f1 + fogcolor[2] * f2;
1213 memset(&m, 0, sizeof(m));
1214 m.pointer_vertex = vertex3f;
1215 m.pointer_color = color;
1221 int nomodelelements[24] =
1233 float nomodelvertex3f[6*3] =
1243 float nomodelcolor4f[6*4] =
1245 0.0f, 0.0f, 0.5f, 1.0f,
1246 0.0f, 0.0f, 0.5f, 1.0f,
1247 0.0f, 0.5f, 0.0f, 1.0f,
1248 0.0f, 0.5f, 0.0f, 1.0f,
1249 0.5f, 0.0f, 0.0f, 1.0f,
1250 0.5f, 0.0f, 0.0f, 1.0f
1253 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1255 const entity_render_t *ent = calldata1;
1257 float f1, f2, *c, diff[3];
1260 R_Mesh_Matrix(&ent->matrix);
1262 memset(&m, 0, sizeof(m));
1263 m.pointer_vertex = nomodelvertex3f;
1265 if (ent->flags & EF_ADDITIVE)
1267 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1268 GL_DepthMask(false);
1270 else if (ent->alpha < 1)
1272 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1273 GL_DepthMask(false);
1277 GL_BlendFunc(GL_ONE, GL_ZERO);
1280 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1283 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1284 m.pointer_color = color4f;
1285 VectorSubtract(ent->origin, r_vieworigin, diff);
1286 f2 = exp(fogdensity/DotProduct(diff, diff));
1288 for (i = 0, c = color4f;i < 6;i++, c += 4)
1290 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1291 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1292 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1296 else if (ent->alpha != 1)
1298 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1299 m.pointer_color = color4f;
1300 for (i = 0, c = color4f;i < 6;i++, c += 4)
1304 m.pointer_color = nomodelcolor4f;
1306 R_Mesh_Draw(0, 6, 8, nomodelelements);
1309 void R_DrawNoModel(entity_render_t *ent)
1311 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1312 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1314 // R_DrawNoModelCallback(ent, 0);
1317 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1319 vec3_t right1, right2, diff, normal;
1321 VectorSubtract (org2, org1, normal);
1323 // calculate 'right' vector for start
1324 VectorSubtract (r_vieworigin, org1, diff);
1325 CrossProduct (normal, diff, right1);
1326 VectorNormalize (right1);
1328 // calculate 'right' vector for end
1329 VectorSubtract (r_vieworigin, org2, diff);
1330 CrossProduct (normal, diff, right2);
1331 VectorNormalize (right2);
1333 vert[ 0] = org1[0] + width * right1[0];
1334 vert[ 1] = org1[1] + width * right1[1];
1335 vert[ 2] = org1[2] + width * right1[2];
1336 vert[ 3] = org1[0] - width * right1[0];
1337 vert[ 4] = org1[1] - width * right1[1];
1338 vert[ 5] = org1[2] - width * right1[2];
1339 vert[ 6] = org2[0] - width * right2[0];
1340 vert[ 7] = org2[1] - width * right2[1];
1341 vert[ 8] = org2[2] - width * right2[2];
1342 vert[ 9] = org2[0] + width * right2[0];
1343 vert[10] = org2[1] + width * right2[1];
1344 vert[11] = org2[2] + width * right2[2];
1347 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1349 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)
1356 VectorSubtract(origin, r_vieworigin, diff);
1357 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1360 R_Mesh_Matrix(&r_identitymatrix);
1361 GL_BlendFunc(blendfunc1, blendfunc2);
1362 GL_DepthMask(false);
1363 GL_DepthTest(!depthdisable);
1365 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1366 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1367 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1368 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1369 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1370 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1371 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1372 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1373 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1374 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1375 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1376 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1378 memset(&m, 0, sizeof(m));
1379 m.tex[0] = R_GetTexture(texture);
1380 m.pointer_texcoord[0] = spritetexcoord2f;
1381 m.pointer_vertex = varray_vertex3f;
1383 GL_Color(cr, cg, cb, ca);
1384 R_Mesh_Draw(0, 4, 2, polygonelements);
1387 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1391 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1392 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1394 if (i == mesh->numvertices)
1396 if (mesh->numvertices < mesh->maxvertices)
1398 VectorCopy(v, vertex3f);
1399 mesh->numvertices++;
1401 return mesh->numvertices;
1407 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1411 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1412 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1413 e = mesh->element3i + mesh->numtriangles * 3;
1414 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1416 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1417 if (mesh->numtriangles < mesh->maxtriangles)
1422 mesh->numtriangles++;
1424 element[1] = element[2];
1428 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1430 int planenum, planenum2;
1433 mplane_t *plane, *plane2;
1434 float temppoints[2][256*3];
1435 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1439 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1440 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1442 if (planenum2 == planenum)
1444 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);
1447 if (tempnumpoints < 3)
1449 // generate elements forming a triangle fan for this polygon
1450 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1454 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1456 // we don't need to set currentframe if t->animated is false because
1457 // it was already set up by the texture loader for non-animating
1460 t->currentframe = 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];
1461 t = t->currentframe;
1463 t->currentmaterialflags = t->basematerialflags;
1464 t->currentalpha = ent->alpha;
1465 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1466 t->currentalpha *= r_wateralpha.value;
1467 if (!(ent->flags & RENDER_LIGHT))
1468 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1469 if (ent->effects & EF_ADDITIVE)
1470 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1471 else if (t->currentalpha < 1)
1472 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1475 void R_UpdateAllTextureInfo(entity_render_t *ent)
1479 for (i = 0;i < ent->model->num_textures;i++)
1480 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1483 static void RSurf_DeformVertices(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1486 float center[3], forward[3], right[3], up[3], v[4][3];
1487 matrix4x4_t matrix1, imatrix1;
1488 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1490 // a single autosprite surface can contain multiple sprites...
1491 VectorClear(forward);
1493 VectorSet(up, 0, 0, 1);
1494 for (j = 0;j < surface->num_vertices - 3;j += 4)
1496 VectorClear(center);
1497 for (i = 0;i < 4;i++)
1498 VectorAdd(center, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1499 VectorScale(center, 0.25f, center);
1500 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1501 Matrix4x4_FromVectors(&matrix1, (surface->groupmesh->data_normal3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_svector3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
1502 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1503 for (i = 0;i < 4;i++)
1504 Matrix4x4_Transform(&imatrix1, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1505 forward[0] = modelorg[0] - center[0];
1506 forward[1] = modelorg[1] - center[1];
1507 VectorNormalize(forward);
1508 right[0] = forward[1];
1509 right[1] = -forward[0];
1510 for (i = 0;i < 4;i++)
1511 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1514 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1516 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1517 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1518 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1519 // a single autosprite surface can contain multiple sprites...
1520 for (j = 0;j < surface->num_vertices - 3;j += 4)
1522 VectorClear(center);
1523 for (i = 0;i < 4;i++)
1524 VectorAdd(center, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1525 VectorScale(center, 0.25f, center);
1526 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1527 Matrix4x4_FromVectors(&matrix1, (surface->groupmesh->data_normal3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_svector3f + 3 * surface->num_firstvertex) + j*3, (surface->groupmesh->data_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
1528 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1529 for (i = 0;i < 4;i++)
1530 Matrix4x4_Transform(&imatrix1, (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1531 for (i = 0;i < 4;i++)
1532 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1536 memcpy((varray_vertex3f + 3 * surface->num_firstvertex), (surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), sizeof(float[3]) * surface->num_vertices);
1539 // any sort of deformvertices call is *VERY* rare, so this must be optimized
1540 // to skip deformvertices quickly!
1542 #define RSurf_GetVertexPointer(ent, texture, surface, modelorg) ((texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) ? (RSurf_DeformVertices(ent, texture, surface, modelorg), varray_vertex3f) : surface->groupmesh->data_vertex3f)
1544 static float *RSurf_GetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1546 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
1548 RSurf_DeformVertices(ent, texture, surface, modelorg);
1549 return varray_vertex3f;
1552 return surface->groupmesh->data_vertex3f;
1556 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1559 int texturesurfaceindex;
1560 const float *v, *vertex3f;
1563 float f, r, g, b, a, base, colorscale;
1564 const msurface_t *surface;
1565 qboolean dolightmap;
1571 qboolean fogallpasses;
1572 qboolean waterscrolling;
1573 surfmesh_t *groupmesh;
1574 rtexture_t *lightmaptexture;
1576 texture = texture->currentframe;
1577 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1579 c_faces += texturenumsurfaces;
1580 // gl_lightmaps debugging mode skips normal texturing
1581 if (gl_lightmaps.integer)
1583 GL_BlendFunc(GL_ONE, GL_ZERO);
1586 qglDisable(GL_CULL_FACE);
1587 GL_Color(1, 1, 1, 1);
1588 memset(&m, 0, sizeof(m));
1590 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1592 surface = texturesurfacelist[texturesurfaceindex];
1593 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1594 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1595 R_Mesh_ColorPointer(surface->lightmaptexture ? NULL : surface->groupmesh->data_lightmapcolor4f);
1596 R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f);
1597 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1598 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1599 GL_LockArrays(0, 0);
1601 qglEnable(GL_CULL_FACE);
1604 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1605 GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT));
1606 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
1607 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1608 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
1609 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1611 GL_BlendFunc(GL_ONE, GL_ZERO);
1612 // water waterscrolling in texture matrix
1613 waterscrolling = (texture->currentmaterialflags & MATERIALFLAG_WATER) && r_waterscroll.value != 0;
1614 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1615 qglDisable(GL_CULL_FACE);
1616 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
1620 skyrendernow = false;
1621 if (skyrendermasked)
1624 // LordHavoc: HalfLife maps have freaky skypolys...
1625 //if (!ent->model->brush.ishlbsp)
1627 R_Mesh_Matrix(&ent->matrix);
1628 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
1629 if (skyrendermasked)
1631 // depth-only (masking)
1632 GL_ColorMask(0,0,0,0);
1633 // just to make sure that braindead drivers don't draw anything
1634 // despite that colormask...
1635 GL_BlendFunc(GL_ZERO, GL_ONE);
1640 GL_BlendFunc(GL_ONE, GL_ZERO);
1644 memset(&m, 0, sizeof(m));
1646 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1648 surface = texturesurfacelist[texturesurfaceindex];
1649 R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f);
1650 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1651 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1652 GL_LockArrays(0, 0);
1654 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1657 else if ((texture->currentmaterialflags & MATERIALFLAG_WATER) && r_watershader.value && gl_textureshader && !texture->skin.glow && !fogenabled && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1)
1659 // NVIDIA Geforce3 distortion texture shader on water
1660 float args[4] = {0.05f,0,0,0.04f};
1661 memset(&m, 0, sizeof(m));
1662 m.tex[0] = R_GetTexture(r_texture_distorttexture[(int)(r_refdef.time * 16)&63]);
1663 m.tex[1] = R_GetTexture(texture->skin.base);
1664 m.texcombinergb[0] = GL_REPLACE;
1665 m.texcombinergb[1] = GL_REPLACE;
1666 Matrix4x4_CreateFromQuakeEntity(&m.texmatrix[0], 0, 0, 0, 0, 0, 0, r_watershader.value);
1667 m.texmatrix[1] = r_waterscrollmatrix;
1670 GL_Color(1, 1, 1, texture->currentalpha);
1671 GL_ActiveTexture(0);
1672 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1673 GL_ActiveTexture(1);
1674 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV);
1675 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB);
1676 qglTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, &args[0]);
1677 qglEnable(GL_TEXTURE_SHADER_NV);
1679 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1681 surface = texturesurfacelist[texturesurfaceindex];
1682 R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
1683 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1684 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1685 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1686 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1687 GL_LockArrays(0, 0);
1690 qglDisable(GL_TEXTURE_SHADER_NV);
1691 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1692 GL_ActiveTexture(0);
1694 else if (texture->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1696 // normal surface (wall or water)
1698 dolightmap = !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT);
1699 doambient = r_ambient.value >= (1/64.0f);
1700 dodetail = r_detailtextures.integer && texture->skin.detail != NULL && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
1701 doglow = texture->skin.glow != NULL;
1702 dofogpass = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD);
1703 fogallpasses = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
1704 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
1706 if (dobase && dolightmap && gl_combine.integer)
1709 memset(&m, 0, sizeof(m));
1710 m.tex[1] = R_GetTexture(texture->skin.base);
1712 m.texmatrix[1] = r_waterscrollmatrix;
1713 m.texrgbscale[1] = 2;
1714 m.pointer_color = varray_color4f;
1717 r = ent->colormod[0] * colorscale;
1718 g = ent->colormod[1] * colorscale;
1719 b = ent->colormod[2] * colorscale;
1720 a = texture->currentalpha;
1721 base = r_ambient.value * (1.0f / 64.0f);
1722 // q3bsp has no lightmap updates, so the lightstylevalue that
1723 // would normally be baked into the lightmaptexture must be
1724 // applied to the color
1725 if (ent->model->brushq1.lightdata)
1727 float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
1732 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1734 surface = texturesurfacelist[texturesurfaceindex];
1735 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
1736 R_Mesh_VertexPointer(vertex3f);
1737 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1738 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1739 if (surface->lightmaptexture)
1741 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1744 R_Mesh_ColorPointer(varray_color4f);
1745 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1747 VectorSubtract(v, modelorg, diff);
1748 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1757 R_Mesh_ColorPointer(NULL);
1758 GL_Color(r, g, b, a);
1763 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1764 R_Mesh_ColorPointer(varray_color4f);
1765 if (!surface->lightmaptexture)
1767 for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4)
1769 c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r;
1770 c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g;
1771 c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b;
1772 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
1776 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1778 VectorSubtract(v, modelorg, diff);
1779 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1780 VectorScale(c, f, c);
1786 R_Mesh_ColorPointer(NULL);
1787 GL_Color(0, 0, 0, a);
1790 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1791 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1792 GL_LockArrays(0, 0);
1798 memset(&m, 0, sizeof(m));
1799 m.tex[0] = R_GetTexture(texture->skin.base);
1801 m.texmatrix[0] = r_waterscrollmatrix;
1802 m.pointer_color = varray_color4f;
1804 if (gl_combine.integer)
1806 m.texrgbscale[0] = 4;
1807 colorscale *= 0.25f;
1810 r = ent->colormod[0] * colorscale;
1811 g = ent->colormod[1] * colorscale;
1812 b = ent->colormod[2] * colorscale;
1813 a = texture->currentalpha;
1816 // q3bsp has no lightmap updates, so the lightstylevalue that
1817 // would normally be baked into the lightmaptexture must be
1818 // applied to the color
1819 if (!ent->model->brushq1.lightdata)
1821 float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
1826 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1828 surface = texturesurfacelist[texturesurfaceindex];
1829 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
1830 R_Mesh_VertexPointer(vertex3f);
1831 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1832 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1837 if (!surface->lightmapinfo)
1838 VectorCopy((surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex) + i*4, c);
1839 else //if (surface->lightmapinfo)
1841 const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1842 float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1843 VectorMA(c, scale, lm, c);
1844 if (surface->lightmapinfo->styles[1] != 255)
1846 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1848 scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1849 VectorMA(c, scale, lm, c);
1850 if (surface->lightmapinfo->styles[2] != 255)
1853 scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1854 VectorMA(c, scale, lm, c);
1855 if (surface->lightmapinfo->styles[3] != 255)
1858 scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1859 VectorMA(c, scale, lm, c);
1869 VectorSubtract(v, modelorg, diff);
1870 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1871 VectorScale(c, f, c);
1873 if (!surface->lightmapinfo && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1874 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
1878 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1879 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1880 GL_LockArrays(0, 0);
1887 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1889 surface = texturesurfacelist[texturesurfaceindex];
1890 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
1891 R_Mesh_VertexPointer(vertex3f);
1892 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1893 if (!surface->lightmapinfo && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1895 R_Mesh_ColorPointer(varray_color4f);
1896 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1898 VectorSubtract(v, modelorg, diff);
1899 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1903 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
1908 R_Mesh_ColorPointer(varray_color4f);
1909 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1911 VectorSubtract(v, modelorg, diff);
1912 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1919 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1920 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1921 GL_LockArrays(0, 0);
1926 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1928 surface = texturesurfacelist[texturesurfaceindex];
1929 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
1930 R_Mesh_VertexPointer(vertex3f);
1931 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1932 if (!surface->lightmaptexture && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1934 R_Mesh_ColorPointer(varray_color4f);
1935 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
1940 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
1945 R_Mesh_ColorPointer(NULL);
1946 GL_Color(r, g, b, a);
1948 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1949 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1950 GL_LockArrays(0, 0);
1958 if (!dolightmap && dobase)
1962 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], 1);
1963 memset(&m, 0, sizeof(m));
1964 m.tex[0] = R_GetTexture(texture->skin.base);
1966 m.texmatrix[0] = r_waterscrollmatrix;
1968 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1970 surface = texturesurfacelist[texturesurfaceindex];
1971 R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
1972 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1973 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1974 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1975 GL_LockArrays(0, 0);
1978 if (r_lightmapintensity <= 0 && dolightmap && dobase)
1982 GL_Color(0, 0, 0, 1);
1983 memset(&m, 0, sizeof(m));
1985 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1987 surface = texturesurfacelist[texturesurfaceindex];
1988 R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
1989 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1990 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1991 GL_LockArrays(0, 0);
1994 if (r_textureunits.integer >= 2 && gl_combine.integer && dolightmap && dobase)
1996 // dualtexture combine
1997 GL_BlendFunc(GL_ONE, GL_ZERO);
2001 memset(&m, 0, sizeof(m));
2002 m.tex[1] = R_GetTexture(texture->skin.base);
2004 m.texmatrix[1] = r_waterscrollmatrix;
2005 m.texrgbscale[1] = 2;
2007 r = ent->colormod[0] * r_lightmapintensity;
2008 g = ent->colormod[1] * r_lightmapintensity;
2009 b = ent->colormod[2] * r_lightmapintensity;
2010 GL_Color(r, g, b, 1);
2011 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2013 R_Mesh_VertexPointer(varray_vertex3f);
2014 if (r == 1 && g == 1 && b == 1)
2016 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2018 surface = texturesurfacelist[texturesurfaceindex];
2019 RSurf_DeformVertices(ent, texture, surface, modelorg);
2020 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2021 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2022 if (surface->lightmaptexture)
2024 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2025 R_Mesh_ColorPointer(NULL);
2027 else //if (r == 1 && g == 1 && b == 1)
2029 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2030 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2032 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2033 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2034 GL_LockArrays(0, 0);
2039 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2041 surface = texturesurfacelist[texturesurfaceindex];
2042 RSurf_DeformVertices(ent, texture, surface, modelorg);
2043 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2044 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2045 if (surface->lightmaptexture)
2047 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2048 R_Mesh_ColorPointer(NULL);
2052 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2053 R_Mesh_ColorPointer(varray_color4f);
2054 for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4)
2056 c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r;
2057 c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g;
2058 c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b;
2059 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3];
2062 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2063 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2064 GL_LockArrays(0, 0);
2070 if (r == 1 && g == 1 && b == 1)
2073 // experimental direct state calls for measuring
2074 // R_Mesh_ call overhead, do not use!
2075 R_Mesh_VertexPointer(varray_vertex3f);
2076 R_Mesh_TexCoordPointer(0, 2, varray_texcoord2f[0]);
2077 R_Mesh_TexCoordPointer(1, 2, varray_texcoord2f[1]);
2078 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2079 R_Mesh_ColorPointer(varray_color4f);
2080 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2082 surface = texturesurfacelist[texturesurfaceindex];
2083 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), surface->groupmesh->data_vertex3f);
2084 qglClientActiveTexture(GL_TEXTURE0_ARB);
2085 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), surface->groupmesh->data_texcoordlightmap2f);
2086 qglClientActiveTexture(GL_TEXTURE1_ARB);
2087 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), surface->groupmesh->data_texcoordtexture2f);
2088 if (surface->lightmaptexture)
2090 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2091 qglDisableClientState(GL_COLOR_ARRAY);
2092 qglColor4f(r, g, b, 1);
2094 else //if (r == 1 && g == 1 && b == 1)
2096 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2097 qglEnableClientState(GL_COLOR_ARRAY);
2098 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), surface->groupmesh->data_lightmapcolor4f);
2100 qglLockArraysEXT(0, surface->num_vertices);
2101 qglDrawRangeElements(GL_TRIANGLES, surface->num_firstvertex, surface->num_firstvertex + surface->num_vertices, surface->num_triangles * 3, GL_UNSIGNED_INT, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2102 qglUnlockArraysEXT();
2106 lightmaptexture = NULL;
2107 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2109 surface = texturesurfacelist[texturesurfaceindex];
2110 if (groupmesh != surface->groupmesh)
2112 groupmesh = surface->groupmesh;
2113 R_Mesh_VertexPointer(groupmesh->data_vertex3f);
2114 R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordlightmap2f);
2115 R_Mesh_TexCoordPointer(1, 2, groupmesh->data_texcoordtexture2f);
2116 if (!lightmaptexture)
2117 R_Mesh_ColorPointer(groupmesh->data_lightmapcolor4f);
2119 if (lightmaptexture != surface->lightmaptexture)
2121 lightmaptexture = surface->lightmaptexture;
2122 if (lightmaptexture)
2124 R_Mesh_TexBind(0, R_GetTexture(lightmaptexture));
2125 R_Mesh_ColorPointer(NULL);
2127 else //if (r == 1 && g == 1 && b == 1)
2129 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2130 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2133 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2134 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2135 GL_LockArrays(0, 0);
2141 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2143 surface = texturesurfacelist[texturesurfaceindex];
2144 R_Mesh_VertexPointer(surface->groupmesh->data_vertex3f);
2145 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2146 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2147 if (surface->lightmaptexture)
2149 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2150 R_Mesh_ColorPointer(NULL);
2154 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2155 R_Mesh_ColorPointer(varray_color4f);
2156 for (i = 0, c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4)
2158 c[0] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+0] * r;
2159 c[1] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+1] * g;
2160 c[2] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+2] * b;
2161 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3];
2164 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2165 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2166 GL_LockArrays(0, 0);
2174 GL_BlendFunc(GL_ONE, GL_ZERO);
2176 GL_Color(1, 1, 1, 1);
2177 memset(&m, 0, sizeof(m));
2179 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2181 R_Mesh_VertexPointer(varray_vertex3f);
2182 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2184 surface = texturesurfacelist[texturesurfaceindex];
2185 RSurf_DeformVertices(ent, texture, surface, modelorg);
2186 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2187 if (surface->lightmaptexture)
2189 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2190 R_Mesh_ColorPointer(NULL);
2192 else //if (r == 1 && g == 1 && b == 1)
2194 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2195 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2197 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2198 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2199 GL_LockArrays(0, 0);
2205 lightmaptexture = NULL;
2206 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2208 surface = texturesurfacelist[texturesurfaceindex];
2209 if (groupmesh != surface->groupmesh)
2211 groupmesh = surface->groupmesh;
2212 R_Mesh_VertexPointer(groupmesh->data_vertex3f);
2213 R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordlightmap2f);
2214 if (!lightmaptexture)
2215 R_Mesh_ColorPointer(groupmesh->data_lightmapcolor4f);
2217 if (lightmaptexture != surface->lightmaptexture)
2219 lightmaptexture = surface->lightmaptexture;
2220 if (lightmaptexture)
2222 R_Mesh_TexBind(0, R_GetTexture(lightmaptexture));
2223 R_Mesh_ColorPointer(NULL);
2225 else //if (r == 1 && g == 1 && b == 1)
2227 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2228 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2231 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2232 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2233 GL_LockArrays(0, 0);
2239 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2240 GL_DepthMask(false);
2241 GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
2242 memset(&m, 0, sizeof(m));
2243 m.tex[0] = R_GetTexture(texture->skin.base);
2245 m.texmatrix[0] = r_waterscrollmatrix;
2247 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2249 R_Mesh_VertexPointer(varray_vertex3f);
2250 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2252 surface = texturesurfacelist[texturesurfaceindex];
2253 RSurf_DeformVertices(ent, texture, surface, modelorg);
2254 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2255 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2256 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2257 GL_LockArrays(0, 0);
2263 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2265 surface = texturesurfacelist[texturesurfaceindex];
2266 if (groupmesh != surface->groupmesh)
2268 groupmesh = surface->groupmesh;
2269 R_Mesh_VertexPointer(groupmesh->data_vertex3f);
2270 R_Mesh_TexCoordPointer(0, 2, groupmesh->data_texcoordtexture2f);
2272 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2273 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2274 GL_LockArrays(0, 0);
2282 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2283 GL_DepthMask(false);
2284 memset(&m, 0, sizeof(m));
2285 m.tex[0] = R_GetTexture(texture->skin.base);
2287 m.texmatrix[0] = r_waterscrollmatrix;
2288 m.pointer_color = varray_color4f;
2290 if (gl_combine.integer)
2292 m.texrgbscale[0] = 4;
2293 colorscale *= 0.25f;
2296 base = r_ambient.value * (1.0f / 64.0f);
2297 r = ent->colormod[0] * colorscale * base;
2298 g = ent->colormod[1] * colorscale * base;
2299 b = ent->colormod[2] * colorscale * base;
2300 a = texture->currentalpha;
2301 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2303 surface = texturesurfacelist[texturesurfaceindex];
2304 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
2305 R_Mesh_VertexPointer(vertex3f);
2306 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2307 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2314 VectorSubtract(v, modelorg, diff);
2315 f = 1 - exp(fogdensity/DotProduct(diff, diff));
2316 VectorScale(c, f, c);
2318 if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2319 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
2323 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2324 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2325 GL_LockArrays(0, 0);
2330 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2331 GL_DepthMask(false);
2332 GL_Color(1, 1, 1, 1);
2333 memset(&m, 0, sizeof(m));
2334 m.tex[0] = R_GetTexture(texture->skin.detail);
2336 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2338 surface = texturesurfacelist[texturesurfaceindex];
2339 R_Mesh_VertexPointer(RSurf_GetVertexPointer(ent, texture, surface, modelorg));
2340 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoorddetail2f);
2341 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2342 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2343 GL_LockArrays(0, 0);
2348 // if glow was not already done using multitexture, do it now.
2349 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2350 GL_DepthMask(false);
2351 memset(&m, 0, sizeof(m));
2352 m.tex[0] = R_GetTexture(texture->skin.glow);
2354 m.texmatrix[0] = r_waterscrollmatrix;
2355 m.pointer_color = varray_color4f;
2358 r = ent->colormod[0] * colorscale;
2359 g = ent->colormod[1] * colorscale;
2360 b = ent->colormod[2] * colorscale;
2361 a = texture->currentalpha;
2364 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2366 surface = texturesurfacelist[texturesurfaceindex];
2367 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
2368 R_Mesh_VertexPointer(vertex3f);
2369 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2370 R_Mesh_ColorPointer(varray_color4f);
2371 if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2373 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2375 VectorSubtract(v, modelorg, diff);
2376 f = 1 - exp(fogdensity/DotProduct(diff, diff));
2380 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
2385 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2387 VectorSubtract(v, modelorg, diff);
2388 f = 1 - exp(fogdensity/DotProduct(diff, diff));
2395 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2396 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2397 GL_LockArrays(0, 0);
2402 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2404 surface = texturesurfacelist[texturesurfaceindex];
2405 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
2406 R_Mesh_VertexPointer(vertex3f);
2407 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2408 if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2410 R_Mesh_ColorPointer(varray_color4f);
2411 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2416 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * a;
2421 R_Mesh_ColorPointer(NULL);
2422 GL_Color(r, g, b, a);
2424 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2425 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2426 GL_LockArrays(0, 0);
2432 // if this is opaque use alpha blend which will darken the earlier
2435 // if this is an alpha blended material, all the earlier passes
2436 // were darkened by fog already, so we only need to add the fog
2437 // color ontop through the fog mask texture
2439 // if this is an additive blended material, all the earlier passes
2440 // were darkened by fog already, and we should not add fog color
2441 // (because the background was not darkened, there is no fog color
2442 // that was lost behind it).
2444 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2446 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2447 GL_DepthMask(false);
2448 memset(&m, 0, sizeof(m));
2449 m.tex[0] = R_GetTexture(texture->skin.fog);
2451 m.texmatrix[0] = r_waterscrollmatrix;
2456 a = texture->currentalpha;
2457 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2459 surface = texturesurfacelist[texturesurfaceindex];
2460 vertex3f = RSurf_GetVertexPointer(ent, texture, surface, modelorg);
2461 R_Mesh_VertexPointer(vertex3f);
2462 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2463 R_Mesh_ColorPointer(varray_color4f);
2464 //RSurf_FogPassColors_Vertex3f_Color4f((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], texture->currentalpha, 1, surface->num_vertices, modelorg);
2465 if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2467 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2469 VectorSubtract(v, modelorg, diff);
2470 f = exp(fogdensity/DotProduct(diff, diff));
2474 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * f * a;
2479 for (i = 0, v = (vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2481 VectorSubtract(v, modelorg, diff);
2482 f = exp(fogdensity/DotProduct(diff, diff));
2489 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2490 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2491 GL_LockArrays(0, 0);
2495 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2496 qglEnable(GL_CULL_FACE);
2499 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2501 const entity_render_t *ent = calldata1;
2502 const msurface_t *surface = ent->model->data_surfaces + calldata2;
2506 texture = surface->texture;
2507 if (texture->basematerialflags & MATERIALFLAG_SKY)
2508 return; // transparent sky is too difficult
2509 R_UpdateTextureInfo(ent, texture);
2511 R_Mesh_Matrix(&ent->matrix);
2512 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2513 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2516 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2518 int texturesurfaceindex;
2519 const msurface_t *surface;
2520 vec3_t tempcenter, center;
2521 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2523 // drawing sky transparently would be too difficult
2524 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2526 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2528 surface = texturesurfacelist[texturesurfaceindex];
2529 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2530 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2531 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2532 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2533 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2538 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2541 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2542 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2544 int i, j, f, flagsmask;
2545 msurface_t *surface, **surfacechain;
2546 texture_t *t, *texture;
2547 model_t *model = ent->model;
2549 const int maxsurfacelist = 1024;
2550 int numsurfacelist = 0;
2551 const msurface_t *surfacelist[1024];
2554 R_Mesh_Matrix(&ent->matrix);
2555 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2557 // update light styles
2558 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2560 for (i = 0;i < model->brushq1.light_styles;i++)
2562 if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
2564 model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
2565 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2566 for (;(surface = *surfacechain);surfacechain++)
2567 surface->cached_dlight = true;
2572 R_UpdateAllTextureInfo(ent);
2573 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2578 if (ent == r_refdef.worldentity)
2580 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2582 if (!r_worldsurfacevisible[j])
2584 if (t != surface->texture)
2588 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2591 t = surface->texture;
2592 f = t->currentmaterialflags & flagsmask;
2593 texture = t->currentframe;
2595 if (f && surface->num_triangles)
2597 // if lightmap parameters changed, rebuild lightmap texture
2598 if (surface->cached_dlight && surface->lightmapinfo->samples)
2599 R_BuildLightMap(ent, surface);
2600 // add face to draw list
2601 surfacelist[numsurfacelist++] = surface;
2602 if (numsurfacelist >= maxsurfacelist)
2604 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2612 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2614 if (t != surface->texture)
2618 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2621 t = surface->texture;
2622 f = t->currentmaterialflags & flagsmask;
2623 texture = t->currentframe;
2625 if (f && surface->num_triangles)
2627 // if lightmap parameters changed, rebuild lightmap texture
2628 if (surface->cached_dlight && surface->lightmapinfo->samples)
2629 R_BuildLightMap(ent, surface);
2630 // add face to draw list
2631 surfacelist[numsurfacelist++] = surface;
2632 if (numsurfacelist >= maxsurfacelist)
2634 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2641 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);