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 rtexturepool_t *r_main_texturepool;
114 rtexture_t *r_bloom_texture_screen;
115 rtexture_t *r_bloom_texture_bloom;
116 rtexture_t *r_texture_blanknormalmap;
117 rtexture_t *r_texture_white;
118 rtexture_t *r_texture_black;
119 rtexture_t *r_texture_notexture;
120 rtexture_t *r_texture_whitecube;
121 rtexture_t *r_texture_normalizationcube;
122 rtexture_t *r_texture_detailtextures[NUM_DETAILTEXTURES];
123 rtexture_t *r_texture_distorttexture[64];
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_BuildDetailTextures (void)
226 float vc[3], vx[3], vy[3], vn[3], lightdir[3];
227 #define DETAILRESOLUTION 256
228 qbyte (*data)[DETAILRESOLUTION][4];
229 qbyte (*noise)[DETAILRESOLUTION];
231 // Allocate the buffers dynamically to avoid having such big guys on the stack
232 data = Mem_Alloc(tempmempool, DETAILRESOLUTION * sizeof(*data));
233 noise = Mem_Alloc(tempmempool, DETAILRESOLUTION * sizeof(*noise));
238 VectorNormalize(lightdir);
239 for (i = 0;i < NUM_DETAILTEXTURES;i++)
241 fractalnoise(&noise[0][0], DETAILRESOLUTION, DETAILRESOLUTION >> 4);
242 for (y = 0;y < DETAILRESOLUTION;y++)
244 for (x = 0;x < DETAILRESOLUTION;x++)
248 vc[2] = noise[y][x] * (1.0f / 32.0f);
251 vx[2] = noise[y][(x + 1) % DETAILRESOLUTION] * (1.0f / 32.0f);
254 vy[2] = noise[(y + 1) % DETAILRESOLUTION][x] * (1.0f / 32.0f);
255 VectorSubtract(vx, vc, vx);
256 VectorSubtract(vy, vc, vy);
257 CrossProduct(vx, vy, vn);
259 light = 128 - DotProduct(vn, lightdir) * 128;
260 light = bound(0, light, 255);
261 data[y][x][0] = data[y][x][1] = data[y][x][2] = light;
265 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);
272 static qbyte R_MorphDistortTexture (double y0, double y1, double y2, double y3, double morph)
274 int m = (int)(((y1 + y3 - (y0 + y2)) * morph * morph * morph) +
275 ((2 * (y0 - y1) + y2 - y3) * morph * morph) +
276 ((y2 - y0) * morph) +
278 return (qbyte)bound(0, m, 255);
281 static void R_BuildDistortTexture (void)
284 #define DISTORTRESOLUTION 32
285 qbyte data[5][DISTORTRESOLUTION][DISTORTRESOLUTION][2];
289 for (y=0; y<DISTORTRESOLUTION; y++)
291 for (x=0; x<DISTORTRESOLUTION; x++)
293 data[i][y][x][0] = rand () & 255;
294 data[i][y][x][1] = rand () & 255;
303 r_texture_distorttexture[i*16+j] = NULL;
304 if (gl_textureshader)
306 for (y=0; y<DISTORTRESOLUTION; y++)
308 for (x=0; x<DISTORTRESOLUTION; x++)
310 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);
311 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);
314 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);
320 static void R_BuildBlankTextures(void)
323 data[0] = 128; // normal X
324 data[1] = 128; // normal Y
325 data[2] = 255; // normal Z
326 data[3] = 128; // height
327 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
332 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
337 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
340 static void R_BuildNoTexture(void)
343 qbyte pix[16][16][4];
344 // this makes a light grey/dark grey checkerboard texture
345 for (y = 0;y < 16;y++)
347 for (x = 0;x < 16;x++)
349 if ((y < 8) ^ (x < 8))
365 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
368 static void R_BuildWhiteCube(void)
371 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
372 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
373 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
374 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
375 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
376 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
377 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
380 static void R_BuildNormalizationCube(void)
384 vec_t s, t, intensity;
386 qbyte data[6][NORMSIZE][NORMSIZE][4];
387 for (side = 0;side < 6;side++)
389 for (y = 0;y < NORMSIZE;y++)
391 for (x = 0;x < NORMSIZE;x++)
393 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
394 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
428 intensity = 127.0f / sqrt(DotProduct(v, v));
429 data[side][y][x][0] = 128.0f + intensity * v[0];
430 data[side][y][x][1] = 128.0f + intensity * v[1];
431 data[side][y][x][2] = 128.0f + intensity * v[2];
432 data[side][y][x][3] = 255;
436 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
439 void gl_main_start(void)
441 r_main_texturepool = R_AllocTexturePool();
442 r_bloom_texture_screen = NULL;
443 r_bloom_texture_bloom = NULL;
444 R_BuildBlankTextures();
446 R_BuildDetailTextures();
447 R_BuildDistortTexture();
448 if (gl_texturecubemap)
451 R_BuildNormalizationCube();
455 void gl_main_shutdown(void)
457 R_FreeTexturePool(&r_main_texturepool);
458 r_bloom_texture_screen = NULL;
459 r_bloom_texture_bloom = NULL;
460 r_texture_blanknormalmap = NULL;
461 r_texture_white = NULL;
462 r_texture_black = NULL;
463 r_texture_whitecube = NULL;
464 r_texture_normalizationcube = NULL;
467 extern void CL_ParseEntityLump(char *entitystring);
468 void gl_main_newmap(void)
470 // FIXME: move this code to client
472 char *entities, entname[MAX_QPATH];
476 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
477 l = (int)strlen(entname) - 4;
478 if (l >= 0 && !strcmp(entname + l, ".bsp"))
480 strcpy(entname + l, ".ent");
481 if ((entities = FS_LoadFile(entname, tempmempool, true)))
483 CL_ParseEntityLump(entities);
488 if (cl.worldmodel->brush.entities)
489 CL_ParseEntityLump(cl.worldmodel->brush.entities);
493 void GL_Main_Init(void)
495 Matrix4x4_CreateIdentity(&r_identitymatrix);
496 // FIXME: move this to client?
498 Cvar_RegisterVariable(&r_showtris);
499 Cvar_RegisterVariable(&r_drawentities);
500 Cvar_RegisterVariable(&r_drawviewmodel);
501 Cvar_RegisterVariable(&r_speeds);
502 Cvar_RegisterVariable(&r_fullbrights);
503 Cvar_RegisterVariable(&r_wateralpha);
504 Cvar_RegisterVariable(&r_dynamic);
505 Cvar_RegisterVariable(&r_fullbright);
506 Cvar_RegisterVariable(&r_textureunits);
507 Cvar_RegisterVariable(&r_lerpsprites);
508 Cvar_RegisterVariable(&r_lerpmodels);
509 Cvar_RegisterVariable(&r_waterscroll);
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(&r_smoothnormals_areaweighting);
517 Cvar_RegisterVariable(&developer_texturelogging);
518 Cvar_RegisterVariable(&gl_lightmaps);
519 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
520 Cvar_SetValue("r_fullbrights", 0);
521 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
524 static vec3_t r_farclip_origin;
525 static vec3_t r_farclip_direction;
526 static vec_t r_farclip_directiondist;
527 static vec_t r_farclip_meshfarclip;
528 static int r_farclip_directionbit0;
529 static int r_farclip_directionbit1;
530 static int r_farclip_directionbit2;
532 // enlarge farclip to accomodate box
533 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
536 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
537 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
538 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
539 if (r_farclip_meshfarclip < d)
540 r_farclip_meshfarclip = d;
543 // return farclip value
544 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
548 VectorCopy(origin, r_farclip_origin);
549 VectorCopy(direction, r_farclip_direction);
550 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
551 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
552 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
553 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
554 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
556 if (r_refdef.worldmodel)
557 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
558 for (i = 0;i < r_refdef.numentities;i++)
559 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
561 return r_farclip_meshfarclip - r_farclip_directiondist;
564 extern void R_Textures_Init(void);
565 extern void GL_Draw_Init(void);
566 extern void GL_Main_Init(void);
567 extern void R_Shadow_Init(void);
568 extern void R_Sky_Init(void);
569 extern void GL_Surf_Init(void);
570 extern void R_Crosshairs_Init(void);
571 extern void R_Light_Init(void);
572 extern void R_Particles_Init(void);
573 extern void R_Explosion_Init(void);
574 extern void gl_backend_init(void);
575 extern void Sbar_Init(void);
576 extern void R_LightningBeams_Init(void);
577 extern void Mod_RenderInit(void);
579 void Render_Init(void)
595 R_LightningBeams_Init();
604 extern char *ENGINE_EXTENSIONS;
607 VID_CheckExtensions();
609 // LordHavoc: report supported extensions
610 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
612 // clear to black (loading plaque will be seen over this)
613 qglClearColor(0,0,0,1);
614 qglClear(GL_COLOR_BUFFER_BIT);
617 int R_CullBox(const vec3_t mins, const vec3_t maxs)
621 for (i = 0;i < 4;i++)
628 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
632 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
636 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
640 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
644 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
648 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
652 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
656 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
664 //==================================================================================
666 static void R_MarkEntities (void)
669 entity_render_t *ent;
671 if (!r_drawentities.integer)
674 r_refdef.worldentity->visframe = r_framecount;
675 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
676 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
678 // worldmodel can check visibility
679 for (i = 0;i < r_refdef.numentities;i++)
681 ent = r_refdef.entities[i];
682 Mod_CheckLoaded(ent->model);
683 // some of the renderer still relies on origin...
684 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
685 // some of the renderer still relies on scale...
686 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
687 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)))
689 R_UpdateEntLights(ent);
690 ent->visframe = r_framecount;
696 // no worldmodel or it can't check visibility
697 for (i = 0;i < r_refdef.numentities;i++)
699 ent = r_refdef.entities[i];
700 Mod_CheckLoaded(ent->model);
701 // some of the renderer still relies on origin...
702 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
703 // some of the renderer still relies on scale...
704 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
705 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
707 R_UpdateEntLights(ent);
708 ent->visframe = r_framecount;
714 // only used if skyrendermasked, and normally returns false
715 int R_DrawBrushModelsSky (void)
718 entity_render_t *ent;
720 if (!r_drawentities.integer)
724 for (i = 0;i < r_refdef.numentities;i++)
726 ent = r_refdef.entities[i];
727 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
729 ent->model->DrawSky(ent);
736 void R_DrawNoModel(entity_render_t *ent);
737 void R_DrawModels(void)
740 entity_render_t *ent;
742 if (!r_drawentities.integer)
745 for (i = 0;i < r_refdef.numentities;i++)
747 ent = r_refdef.entities[i];
748 if (ent->visframe == r_framecount)
750 if (ent->model && ent->model->Draw != NULL)
751 ent->model->Draw(ent);
758 static void R_SetFrustum(void)
760 // break apart the view matrix into vectors for various purposes
761 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
762 VectorNegate(r_viewleft, r_viewright);
764 // LordHavoc: note to all quake engine coders, the special case for 90
765 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
768 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
769 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
770 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
771 PlaneClassify(&frustum[0]);
773 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
774 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
775 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
776 PlaneClassify(&frustum[1]);
778 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
779 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
780 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
781 PlaneClassify(&frustum[2]);
783 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
784 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
785 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
786 PlaneClassify(&frustum[3]);
789 VectorCopy(r_viewforward, frustum[4].normal);
790 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
791 PlaneClassify(&frustum[4]);
794 static void R_BlendView(void)
798 if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
801 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
804 R_Mesh_Matrix(&r_identitymatrix);
805 // vertex coordinates for a quad that covers the screen exactly
806 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
807 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
808 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
809 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
810 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)
812 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
813 float xoffset, yoffset, r;
815 // set the (poorly named) screenwidth and screenheight variables to
816 // a power of 2 at least as large as the screen, these will define the
817 // size of the texture to allocate
818 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
819 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
820 // allocate textures as needed
821 if (!r_bloom_texture_screen)
822 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
823 if (!r_bloom_texture_bloom)
824 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
825 // set bloomwidth and bloomheight to the bloom resolution that will be
826 // used (often less than the screen resolution for faster rendering)
827 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
828 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
829 // set up a texcoord array for the full resolution screen image
830 // (we have to keep this around to copy back during final render)
831 varray_texcoord2f[0][0] = 0;
832 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
833 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
834 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
835 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
836 varray_texcoord2f[0][5] = 0;
837 varray_texcoord2f[0][6] = 0;
838 varray_texcoord2f[0][7] = 0;
839 // set up a texcoord array for the reduced resolution bloom image
840 // (which will be additive blended over the screen image)
841 varray_texcoord2f[1][0] = 0;
842 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
843 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
844 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
845 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
846 varray_texcoord2f[1][5] = 0;
847 varray_texcoord2f[1][6] = 0;
848 varray_texcoord2f[1][7] = 0;
849 memset(&m, 0, sizeof(m));
850 m.pointer_vertex = varray_vertex3f;
851 m.pointer_texcoord[0] = varray_texcoord2f[0];
852 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
854 // copy view into the full resolution screen image texture
856 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
858 c_bloomcopypixels += r_view_width * r_view_height;
859 // now scale it down to the bloom size and raise to a power of itself
860 // to darken it (this leaves the really bright stuff bright, and
861 // everything else becomes very dark)
862 // TODO: optimize with multitexture or GLSL
863 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
864 GL_BlendFunc(GL_ONE, GL_ZERO);
865 GL_Color(1, 1, 1, 1);
866 R_Mesh_Draw(0, 4, 2, polygonelements);
868 c_bloomdrawpixels += bloomwidth * bloomheight;
869 // render multiple times with a multiply blendfunc to raise to a power
870 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
871 for (x = 1;x < r_bloom_power.integer;x++)
873 R_Mesh_Draw(0, 4, 2, polygonelements);
875 c_bloomdrawpixels += bloomwidth * bloomheight;
877 // we now have a darkened bloom image in the framebuffer, copy it into
878 // the bloom image texture for more processing
879 memset(&m, 0, sizeof(m));
880 m.pointer_vertex = varray_vertex3f;
881 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
882 m.pointer_texcoord[0] = varray_texcoord2f[2];
885 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
887 c_bloomcopypixels += bloomwidth * bloomheight;
888 // blend on at multiple vertical offsets to achieve a vertical blur
889 // TODO: do offset blends using GLSL
890 range = r_bloom_blur.integer * bloomwidth / 320;
891 GL_BlendFunc(GL_ONE, GL_ZERO);
892 for (x = -range;x <= range;x++)
894 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
895 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
896 // compute a texcoord array with the specified x and y offset
897 varray_texcoord2f[2][0] = xoffset+0;
898 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
899 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
900 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
901 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
902 varray_texcoord2f[2][5] = yoffset+0;
903 varray_texcoord2f[2][6] = xoffset+0;
904 varray_texcoord2f[2][7] = yoffset+0;
905 // this r value looks like a 'dot' particle, fading sharply to
906 // black at the edges
907 // (probably not realistic but looks good enough)
908 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
911 GL_Color(r, r, r, 1);
912 R_Mesh_Draw(0, 4, 2, polygonelements);
914 c_bloomdrawpixels += bloomwidth * bloomheight;
915 GL_BlendFunc(GL_ONE, GL_ONE);
917 // copy the vertically blurred bloom view to a texture
919 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
921 c_bloomcopypixels += bloomwidth * bloomheight;
922 // blend the vertically blurred image at multiple offsets horizontally
923 // to finish the blur effect
924 // TODO: do offset blends using GLSL
925 range = r_bloom_blur.integer * bloomwidth / 320;
926 GL_BlendFunc(GL_ONE, GL_ZERO);
927 for (x = -range;x <= range;x++)
929 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
930 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
931 // compute a texcoord array with the specified x and y offset
932 varray_texcoord2f[2][0] = xoffset+0;
933 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
934 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
935 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
936 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
937 varray_texcoord2f[2][5] = yoffset+0;
938 varray_texcoord2f[2][6] = xoffset+0;
939 varray_texcoord2f[2][7] = yoffset+0;
940 // this r value looks like a 'dot' particle, fading sharply to
941 // black at the edges
942 // (probably not realistic but looks good enough)
943 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
946 GL_Color(r, r, r, 1);
947 R_Mesh_Draw(0, 4, 2, polygonelements);
949 c_bloomdrawpixels += bloomwidth * bloomheight;
950 GL_BlendFunc(GL_ONE, GL_ONE);
952 // copy the blurred bloom view to a texture
954 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
956 c_bloomcopypixels += bloomwidth * bloomheight;
957 // go back to full view area
958 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
959 // put the original screen image back in place and blend the bloom
961 memset(&m, 0, sizeof(m));
962 m.pointer_vertex = varray_vertex3f;
963 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
964 m.pointer_texcoord[0] = varray_texcoord2f[0];
966 dobloomblend = false;
968 // do both in one pass if possible
969 if (r_textureunits.integer >= 2 && gl_combine.integer)
971 dobloomblend = false;
972 m.texcombinergb[1] = GL_ADD;
973 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
974 m.pointer_texcoord[1] = varray_texcoord2f[1];
980 GL_BlendFunc(GL_ONE, GL_ZERO);
982 R_Mesh_Draw(0, 4, 2, polygonelements);
984 c_bloomdrawpixels += r_view_width * r_view_height;
985 // now blend on the bloom texture if multipass
988 memset(&m, 0, sizeof(m));
989 m.pointer_vertex = varray_vertex3f;
990 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
991 m.pointer_texcoord[0] = varray_texcoord2f[1];
993 GL_BlendFunc(GL_ONE, GL_ONE);
995 R_Mesh_Draw(0, 4, 2, polygonelements);
997 c_bloomdrawpixels += r_view_width * r_view_height;
1000 if (r_refdef.viewblend[3] >= 0.01f)
1002 // apply a color tint to the whole view
1003 memset(&m, 0, sizeof(m));
1004 m.pointer_vertex = varray_vertex3f;
1006 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1007 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1008 R_Mesh_Draw(0, 4, 2, polygonelements);
1012 void R_RenderScene(void);
1014 matrix4x4_t r_waterscrollmatrix;
1021 void R_RenderView(void)
1023 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1024 return; //Host_Error ("R_RenderView: NULL worldmodel");
1026 r_view_width = bound(0, r_refdef.width, vid.width);
1027 r_view_height = bound(0, r_refdef.height, vid.height);
1029 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1030 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1032 r_view_fov_x = bound(1, r_refdef.fov_x, 170);
1033 r_view_fov_y = bound(1, r_refdef.fov_y, 170);
1034 r_view_matrix = r_refdef.viewentitymatrix;
1035 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1036 r_rtworld = r_shadow_realtime_world.integer;
1037 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1038 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1039 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1040 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1042 // GL is weird because it's bottom to top, r_view_y is top to bottom
1043 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1044 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1045 GL_ScissorTest(true);
1051 R_TimeReport("setup");
1053 qglDepthFunc(GL_LEQUAL);
1054 qglPolygonOffset(0, 0);
1055 qglEnable(GL_POLYGON_OFFSET_FILL);
1059 qglPolygonOffset(0, 0);
1060 qglDisable(GL_POLYGON_OFFSET_FILL);
1063 R_TimeReport("blendview");
1065 GL_Scissor(0, 0, vid.width, vid.height);
1066 GL_ScissorTest(false);
1069 extern void R_DrawLightningBeams (void);
1070 void R_RenderScene(void)
1072 // don't let sound skip if going slow
1073 if (r_refdef.extraupdate)
1078 R_MeshQueue_BeginScene();
1080 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1084 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1085 if (r_rtworldshadows || r_rtdlightshadows)
1086 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
1088 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
1090 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1092 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);
1096 R_WorldVisibility();
1097 R_TimeReport("worldvis");
1100 R_TimeReport("markentity");
1102 R_Shadow_UpdateWorldLightSelection();
1104 // don't let sound skip if going slow
1105 if (r_refdef.extraupdate)
1108 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1109 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1111 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1112 R_TimeReport("worldsky");
1115 if (R_DrawBrushModelsSky())
1116 R_TimeReport("bmodelsky");
1118 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1119 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1121 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1122 R_TimeReport("world");
1125 // don't let sound skip if going slow
1126 if (r_refdef.extraupdate)
1129 GL_ShowTrisColor(0, 0.015, 0, 1);
1132 R_TimeReport("models");
1134 // don't let sound skip if going slow
1135 if (r_refdef.extraupdate)
1138 GL_ShowTrisColor(0, 0, 0.033, 1);
1139 R_ShadowVolumeLighting(false);
1140 R_TimeReport("rtlights");
1142 // don't let sound skip if going slow
1143 if (r_refdef.extraupdate)
1146 GL_ShowTrisColor(0.1, 0, 0, 1);
1148 R_DrawLightningBeams();
1149 R_TimeReport("lightning");
1152 R_TimeReport("particles");
1155 R_TimeReport("explosions");
1157 R_MeshQueue_RenderTransparent();
1158 R_TimeReport("drawtrans");
1161 R_TimeReport("coronas");
1163 R_DrawWorldCrosshair();
1164 R_TimeReport("crosshair");
1166 R_MeshQueue_Render();
1167 R_MeshQueue_EndScene();
1169 if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1171 R_ShadowVolumeLighting(true);
1172 R_TimeReport("visiblevolume");
1175 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1177 // don't let sound skip if going slow
1178 if (r_refdef.extraupdate)
1183 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1186 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1188 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1189 GL_DepthMask(false);
1191 R_Mesh_Matrix(&r_identitymatrix);
1193 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1194 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1195 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1196 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1197 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1198 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1199 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1200 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1201 R_FillColors(color, 8, cr, cg, cb, ca);
1204 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1206 VectorSubtract(v, r_vieworigin, diff);
1207 f2 = exp(fogdensity/DotProduct(diff, diff));
1209 c[0] = c[0] * f1 + fogcolor[0] * f2;
1210 c[1] = c[1] * f1 + fogcolor[1] * f2;
1211 c[2] = c[2] * f1 + fogcolor[2] * f2;
1214 memset(&m, 0, sizeof(m));
1215 m.pointer_vertex = vertex3f;
1216 m.pointer_color = color;
1222 int nomodelelements[24] =
1234 float nomodelvertex3f[6*3] =
1244 float nomodelcolor4f[6*4] =
1246 0.0f, 0.0f, 0.5f, 1.0f,
1247 0.0f, 0.0f, 0.5f, 1.0f,
1248 0.0f, 0.5f, 0.0f, 1.0f,
1249 0.0f, 0.5f, 0.0f, 1.0f,
1250 0.5f, 0.0f, 0.0f, 1.0f,
1251 0.5f, 0.0f, 0.0f, 1.0f
1254 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1256 const entity_render_t *ent = calldata1;
1258 float f1, f2, *c, diff[3];
1261 R_Mesh_Matrix(&ent->matrix);
1263 memset(&m, 0, sizeof(m));
1264 m.pointer_vertex = nomodelvertex3f;
1266 if (ent->flags & EF_ADDITIVE)
1268 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1269 GL_DepthMask(false);
1271 else if (ent->alpha < 1)
1273 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1274 GL_DepthMask(false);
1278 GL_BlendFunc(GL_ONE, GL_ZERO);
1281 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1284 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1285 m.pointer_color = color4f;
1286 VectorSubtract(ent->origin, r_vieworigin, diff);
1287 f2 = exp(fogdensity/DotProduct(diff, diff));
1289 for (i = 0, c = color4f;i < 6;i++, c += 4)
1291 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1292 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1293 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1297 else if (ent->alpha != 1)
1299 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1300 m.pointer_color = color4f;
1301 for (i = 0, c = color4f;i < 6;i++, c += 4)
1305 m.pointer_color = nomodelcolor4f;
1307 R_Mesh_Draw(0, 6, 8, nomodelelements);
1310 void R_DrawNoModel(entity_render_t *ent)
1312 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1313 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1315 // R_DrawNoModelCallback(ent, 0);
1318 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1320 vec3_t right1, right2, diff, normal;
1322 VectorSubtract (org2, org1, normal);
1324 // calculate 'right' vector for start
1325 VectorSubtract (r_vieworigin, org1, diff);
1326 CrossProduct (normal, diff, right1);
1327 VectorNormalize (right1);
1329 // calculate 'right' vector for end
1330 VectorSubtract (r_vieworigin, org2, diff);
1331 CrossProduct (normal, diff, right2);
1332 VectorNormalize (right2);
1334 vert[ 0] = org1[0] + width * right1[0];
1335 vert[ 1] = org1[1] + width * right1[1];
1336 vert[ 2] = org1[2] + width * right1[2];
1337 vert[ 3] = org1[0] - width * right1[0];
1338 vert[ 4] = org1[1] - width * right1[1];
1339 vert[ 5] = org1[2] - width * right1[2];
1340 vert[ 6] = org2[0] - width * right2[0];
1341 vert[ 7] = org2[1] - width * right2[1];
1342 vert[ 8] = org2[2] - width * right2[2];
1343 vert[ 9] = org2[0] + width * right2[0];
1344 vert[10] = org2[1] + width * right2[1];
1345 vert[11] = org2[2] + width * right2[2];
1348 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1350 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)
1357 VectorSubtract(origin, r_vieworigin, diff);
1358 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1361 R_Mesh_Matrix(&r_identitymatrix);
1362 GL_BlendFunc(blendfunc1, blendfunc2);
1363 GL_DepthMask(false);
1364 GL_DepthTest(!depthdisable);
1366 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1367 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1368 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1369 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1370 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1371 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1372 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1373 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1374 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1375 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1376 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1377 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1379 memset(&m, 0, sizeof(m));
1380 m.tex[0] = R_GetTexture(texture);
1381 m.pointer_texcoord[0] = spritetexcoord2f;
1382 m.pointer_vertex = varray_vertex3f;
1384 GL_Color(cr, cg, cb, ca);
1385 R_Mesh_Draw(0, 4, 2, polygonelements);
1388 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1392 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1393 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1395 if (i == mesh->numvertices)
1397 if (mesh->numvertices < mesh->maxvertices)
1399 VectorCopy(v, vertex3f);
1400 mesh->numvertices++;
1402 return mesh->numvertices;
1408 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1412 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1413 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1414 e = mesh->element3i + mesh->numtriangles * 3;
1415 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1417 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1418 if (mesh->numtriangles < mesh->maxtriangles)
1423 mesh->numtriangles++;
1425 element[1] = element[2];
1429 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1431 int planenum, planenum2;
1434 mplane_t *plane, *plane2;
1435 float temppoints[2][256*3];
1436 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1440 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1441 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1443 if (planenum2 == planenum)
1445 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);
1448 if (tempnumpoints < 3)
1450 // generate elements forming a triangle fan for this polygon
1451 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1455 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1457 texture_t *texture = t;
1458 model_t *model = ent->model;
1459 int s = ent->skinnum;
1460 if ((unsigned int)s >= (unsigned int)model->numskins)
1464 if (model->skinscenes)
1466 if (model->skinscenes[s].framecount > 1)
1467 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1469 s = model->skinscenes[s].firstframe;
1472 t = t + s * model->num_surfaces;
1474 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];
1475 texture->currentframe = t;
1476 t->currentmaterialflags = t->basematerialflags;
1477 t->currentalpha = ent->alpha;
1478 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1479 t->currentalpha *= r_wateralpha.value;
1480 if (!(ent->flags & RENDER_LIGHT))
1481 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1482 if (ent->effects & EF_ADDITIVE)
1483 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1484 else if (t->currentalpha < 1)
1485 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1486 if (ent->effects & EF_NODEPTHTEST)
1487 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1488 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1489 t->currenttexmatrix = r_waterscrollmatrix;
1491 t->currenttexmatrix = r_identitymatrix;
1494 void R_UpdateAllTextureInfo(entity_render_t *ent)
1498 for (i = 0;i < ent->model->num_textures;i++)
1499 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1502 float *rsurface_vertex3f;
1503 float *rsurface_svector3f;
1504 float *rsurface_tvector3f;
1505 float *rsurface_normal3f;
1506 float *rsurface_lightmapcolor4f;
1508 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1511 float center[3], forward[3], right[3], up[3], v[4][3];
1512 matrix4x4_t matrix1, imatrix1;
1513 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1515 rsurface_vertex3f = varray_vertex3f;
1516 rsurface_svector3f = NULL;
1517 rsurface_tvector3f = NULL;
1518 rsurface_normal3f = NULL;
1519 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1523 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1524 rsurface_svector3f = surface->groupmesh->data_svector3f;
1525 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1526 rsurface_normal3f = surface->groupmesh->data_normal3f;
1528 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1530 if (!rsurface_svector3f)
1532 rsurface_svector3f = varray_svector3f;
1533 rsurface_tvector3f = varray_tvector3f;
1534 rsurface_normal3f = varray_normal3f;
1535 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);
1537 // a single autosprite surface can contain multiple sprites...
1538 VectorClear(forward);
1540 VectorSet(up, 0, 0, 1);
1541 for (j = 0;j < surface->num_vertices - 3;j += 4)
1543 VectorClear(center);
1544 for (i = 0;i < 4;i++)
1545 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1546 VectorScale(center, 0.25f, center);
1547 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1548 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);
1549 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1550 for (i = 0;i < 4;i++)
1551 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1552 forward[0] = modelorg[0] - center[0];
1553 forward[1] = modelorg[1] - center[1];
1554 VectorNormalize(forward);
1555 right[0] = forward[1];
1556 right[1] = -forward[0];
1557 for (i = 0;i < 4;i++)
1558 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1560 rsurface_vertex3f = varray_vertex3f;
1561 rsurface_svector3f = NULL;
1562 rsurface_tvector3f = NULL;
1563 rsurface_normal3f = NULL;
1565 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1567 if (!rsurface_svector3f)
1569 rsurface_svector3f = varray_svector3f;
1570 rsurface_tvector3f = varray_tvector3f;
1571 rsurface_normal3f = varray_normal3f;
1572 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);
1574 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1575 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1576 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1577 // a single autosprite surface can contain multiple sprites...
1578 for (j = 0;j < surface->num_vertices - 3;j += 4)
1580 VectorClear(center);
1581 for (i = 0;i < 4;i++)
1582 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1583 VectorScale(center, 0.25f, center);
1584 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1585 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);
1586 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1587 for (i = 0;i < 4;i++)
1588 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1589 for (i = 0;i < 4;i++)
1590 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1592 rsurface_vertex3f = varray_vertex3f;
1593 rsurface_svector3f = NULL;
1594 rsurface_tvector3f = NULL;
1595 rsurface_normal3f = NULL;
1597 R_Mesh_VertexPointer(rsurface_vertex3f);
1600 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)
1608 vec4_t ambientcolor4f;
1609 vec3_t diffusecolor;
1610 vec3_t diffusenormal;
1611 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1613 rsurface_lightmapcolor4f = varray_color4f;
1614 if (rsurface_normal3f == NULL)
1616 rsurface_normal3f = varray_normal3f;
1617 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);
1619 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);
1628 r = ambientcolor4f[0];
1629 g = ambientcolor4f[1];
1630 b = ambientcolor4f[2];
1631 a = ambientcolor4f[3];
1632 rsurface_lightmapcolor4f = NULL;
1635 else if (lightmode >= 1)
1637 if (surface->lightmapinfo)
1639 rsurface_lightmapcolor4f = varray_color4f;
1640 for (i = 0, c = rsurface_lightmapcolor4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1642 const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1643 float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1644 VectorScale(lm, scale, c);
1645 if (surface->lightmapinfo->styles[1] != 255)
1647 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1649 scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1650 VectorMA(c, scale, lm, c);
1651 if (surface->lightmapinfo->styles[2] != 255)
1654 scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1655 VectorMA(c, scale, lm, c);
1656 if (surface->lightmapinfo->styles[3] != 255)
1659 scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1660 VectorMA(c, scale, lm, c);
1667 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1670 rsurface_lightmapcolor4f = NULL;
1673 if (rsurface_lightmapcolor4f)
1675 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)
1677 VectorSubtract(v, modelorg, diff);
1678 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1687 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)
1689 VectorSubtract(v, modelorg, diff);
1690 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1697 rsurface_lightmapcolor4f = varray_color4f;
1699 if (applycolor && rsurface_lightmapcolor4f)
1701 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)
1709 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1710 GL_Color(r, g, b, a);
1714 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1717 int texturesurfaceindex;
1721 float colorpants[3], colorshirt[3];
1722 float f, r, g, b, a, colorscale;
1723 const msurface_t *surface;
1724 qboolean dolightmap;
1729 qboolean fogallpasses;
1732 qboolean dofullbrightpants;
1733 qboolean dofullbrightshirt;
1734 qboolean applycolor;
1735 qboolean lightmode = 0;
1736 rtexture_t *basetexture;
1738 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1740 c_faces += texturenumsurfaces;
1741 // FIXME: identify models using a better check than ent->model->shadowmesh
1742 if (!(ent->effects & EF_FULLBRIGHT) && !ent->model->brush.shadowmesh)
1744 // gl_lightmaps debugging mode skips normal texturing
1745 if (gl_lightmaps.integer)
1747 GL_BlendFunc(GL_ONE, GL_ZERO);
1750 qglDisable(GL_CULL_FACE);
1751 GL_Color(1, 1, 1, 1);
1752 memset(&m, 0, sizeof(m));
1754 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1756 surface = texturesurfacelist[texturesurfaceindex];
1757 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1758 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1759 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1760 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, lightmode ? lightmode : !surface->lightmaptexture, false, false);
1761 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1762 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1763 GL_LockArrays(0, 0);
1765 qglEnable(GL_CULL_FACE);
1768 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1769 GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT));
1770 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
1771 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1772 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
1773 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1775 GL_BlendFunc(GL_ONE, GL_ZERO);
1776 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1777 qglDisable(GL_CULL_FACE);
1778 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
1782 skyrendernow = false;
1783 if (skyrendermasked)
1786 // LordHavoc: HalfLife maps have freaky skypolys...
1787 //if (!ent->model->brush.ishlbsp)
1789 R_Mesh_Matrix(&ent->matrix);
1790 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
1791 if (skyrendermasked)
1793 // depth-only (masking)
1794 GL_ColorMask(0,0,0,0);
1795 // just to make sure that braindead drivers don't draw anything
1796 // despite that colormask...
1797 GL_BlendFunc(GL_ZERO, GL_ONE);
1802 GL_BlendFunc(GL_ONE, GL_ZERO);
1806 memset(&m, 0, sizeof(m));
1808 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1810 surface = texturesurfacelist[texturesurfaceindex];
1811 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1812 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1813 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1814 GL_LockArrays(0, 0);
1816 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1819 else if (texture->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1821 // normal surface (wall or water)
1822 dolightmap = !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT);
1823 doambient = r_ambient.value >= (1/64.0f);
1824 dodetail = r_detailtextures.integer && texture->skin.detail != NULL && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
1825 doglow = texture->skin.glow != NULL;
1826 dofogpass = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD);
1827 fogallpasses = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
1828 if (ent->colormap >= 0)
1832 basetexture = texture->skin.base;
1833 dopants = texture->skin.pants != NULL;
1834 doshirt = texture->skin.shirt != NULL;
1835 // 128-224 are backwards ranges
1836 b = (ent->colormap & 0xF) << 4;b += (b >= 128 && b < 224) ? 4 : 12;
1837 dofullbrightpants = b >= 224;
1838 bcolor = (qbyte *) (&palette_complete[b]);
1839 VectorScale(bcolor, (1.0f / 255.0f), colorpants);
1840 // 128-224 are backwards ranges
1841 b = (ent->colormap & 0xF0);b += (b >= 128 && b < 224) ? 4 : 12;
1842 dofullbrightshirt = b >= 224;
1843 bcolor = (qbyte *) (&palette_complete[b]);
1844 VectorScale(bcolor, (1.0f / 255.0f), colorshirt);
1848 basetexture = texture->skin.merged ? texture->skin.merged : texture->skin.base;
1851 dofullbrightshirt = false;
1852 dofullbrightpants = false;
1854 if (dolightmap && r_textureunits.integer >= 2 && gl_combine.integer)
1856 memset(&m, 0, sizeof(m));
1857 m.tex[1] = R_GetTexture(basetexture);
1858 m.texmatrix[1] = texture->currenttexmatrix;
1859 m.texrgbscale[1] = 2;
1860 m.pointer_color = varray_color4f;
1862 // transparent is not affected by r_lightmapintensity
1863 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1864 colorscale = r_lightmapintensity;
1867 // q3bsp has no lightmap updates, so the lightstylevalue that
1868 // would normally be baked into the lightmaptexture must be
1869 // applied to the color
1870 if (ent->model->type == mod_brushq3)
1871 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
1872 r = ent->colormod[0] * colorscale;
1873 g = ent->colormod[1] * colorscale;
1874 b = ent->colormod[2] * colorscale;
1875 a = texture->currentalpha;
1876 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
1877 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1879 surface = texturesurfacelist[texturesurfaceindex];
1880 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1881 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1882 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1883 if (surface->lightmaptexture)
1884 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1886 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1887 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode ? lightmode : !surface->lightmaptexture, applycolor, fogallpasses);
1888 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1889 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1890 GL_LockArrays(0, 0);
1893 else if (dolightmap && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT) && !lightmode)
1896 GL_BlendFunc(GL_ONE, GL_ZERO);
1898 GL_Color(1, 1, 1, 1);
1899 memset(&m, 0, sizeof(m));
1901 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1903 surface = texturesurfacelist[texturesurfaceindex];
1904 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1905 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1906 if (surface->lightmaptexture)
1908 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1909 R_Mesh_ColorPointer(NULL);
1913 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1914 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
1916 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1917 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1918 GL_LockArrays(0, 0);
1920 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1921 GL_DepthMask(false);
1922 GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
1923 memset(&m, 0, sizeof(m));
1924 m.tex[0] = R_GetTexture(basetexture);
1925 m.texmatrix[0] = texture->currenttexmatrix;
1927 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1929 surface = texturesurfacelist[texturesurfaceindex];
1930 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1931 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1932 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1933 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1934 GL_LockArrays(0, 0);
1939 memset(&m, 0, sizeof(m));
1940 m.tex[0] = R_GetTexture(basetexture);
1941 m.texmatrix[0] = texture->currenttexmatrix;
1942 m.pointer_color = varray_color4f;
1944 if (gl_combine.integer)
1946 m.texrgbscale[0] = 2;
1949 // transparent is not affected by r_lightmapintensity
1950 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1951 colorscale *= r_lightmapintensity;
1952 // q3bsp has no lightmap updates, so the lightstylevalue that
1953 // would normally be baked into the lightmaptexture must be
1954 // applied to the color
1955 if (dolightmap && ent->model->type == mod_brushq3)
1956 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
1958 r = ent->colormod[0] * colorscale;
1959 g = ent->colormod[1] * colorscale;
1960 b = ent->colormod[2] * colorscale;
1961 a = texture->currentalpha;
1962 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
1965 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1967 surface = texturesurfacelist[texturesurfaceindex];
1968 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1969 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1970 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, fogallpasses);
1971 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1972 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1973 GL_LockArrays(0, 0);
1978 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1980 surface = texturesurfacelist[texturesurfaceindex];
1981 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1982 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1983 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
1984 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1985 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1986 GL_LockArrays(0, 0);
1992 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1993 memset(&m, 0, sizeof(m));
1994 m.tex[0] = R_GetTexture(texture->skin.pants);
1995 m.texmatrix[0] = texture->currenttexmatrix;
1996 m.pointer_color = varray_color4f;
1998 if (gl_combine.integer)
2000 m.texrgbscale[0] = 2;
2003 // transparent is not affected by r_lightmapintensity
2004 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2005 colorscale *= r_lightmapintensity;
2006 // q3bsp has no lightmap updates, so the lightstylevalue that
2007 // would normally be baked into the lightmaptexture must be
2008 // applied to the color
2009 if (dolightmap && !dofullbrightpants && ent->model->type == mod_brushq3)
2010 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
2012 r = ent->colormod[0] * colorpants[0] * colorscale;
2013 g = ent->colormod[1] * colorpants[1] * colorscale;
2014 b = ent->colormod[2] * colorpants[2] * colorscale;
2015 a = texture->currentalpha;
2016 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2017 if (dolightmap && !dofullbrightpants)
2019 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2021 surface = texturesurfacelist[texturesurfaceindex];
2022 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2023 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2024 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, fogallpasses);
2025 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2026 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2027 GL_LockArrays(0, 0);
2032 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2034 surface = texturesurfacelist[texturesurfaceindex];
2035 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2036 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2037 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2038 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2039 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2040 GL_LockArrays(0, 0);
2046 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2047 memset(&m, 0, sizeof(m));
2048 m.tex[0] = R_GetTexture(texture->skin.shirt);
2049 m.texmatrix[0] = texture->currenttexmatrix;
2050 m.pointer_color = varray_color4f;
2052 if (gl_combine.integer)
2054 m.texrgbscale[0] = 2;
2057 // transparent is not affected by r_lightmapintensity
2058 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2059 colorscale *= r_lightmapintensity;
2060 // q3bsp has no lightmap updates, so the lightstylevalue that
2061 // would normally be baked into the lightmaptexture must be
2062 // applied to the color
2063 if (dolightmap && !dofullbrightshirt && ent->model->type == mod_brushq3)
2064 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
2066 r = ent->colormod[0] * colorshirt[0] * colorscale;
2067 g = ent->colormod[1] * colorshirt[1] * colorscale;
2068 b = ent->colormod[2] * colorshirt[2] * colorscale;
2069 a = texture->currentalpha;
2070 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2071 if (dolightmap && !dofullbrightshirt)
2073 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2075 surface = texturesurfacelist[texturesurfaceindex];
2076 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2077 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2078 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, fogallpasses);
2079 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2080 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2081 GL_LockArrays(0, 0);
2086 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2088 surface = texturesurfacelist[texturesurfaceindex];
2089 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2090 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2091 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2092 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2093 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2094 GL_LockArrays(0, 0);
2101 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2102 GL_DepthMask(false);
2103 memset(&m, 0, sizeof(m));
2104 m.tex[0] = R_GetTexture(texture->skin.base);
2105 m.texmatrix[0] = texture->currenttexmatrix;
2106 m.pointer_color = varray_color4f;
2108 if (gl_combine.integer && (ent->colormod[0] > 1 || ent->colormod[1] > 1 || ent->colormod[2] > 1))
2110 m.texrgbscale[0] = 4;
2114 colorscale *= r_ambient.value * (1.0f / 64.0f);
2115 r = ent->colormod[0] * colorscale;
2116 g = ent->colormod[1] * colorscale;
2117 b = ent->colormod[2] * colorscale;
2118 a = texture->currentalpha;
2119 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2120 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2122 surface = texturesurfacelist[texturesurfaceindex];
2123 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2124 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2125 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2126 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2127 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2128 GL_LockArrays(0, 0);
2133 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2134 GL_DepthMask(false);
2135 GL_Color(1, 1, 1, 1);
2136 memset(&m, 0, sizeof(m));
2137 m.tex[0] = R_GetTexture(texture->skin.detail);
2139 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2141 surface = texturesurfacelist[texturesurfaceindex];
2142 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2143 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoorddetail2f);
2144 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2145 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2146 GL_LockArrays(0, 0);
2151 // if glow was not already done using multitexture, do it now.
2152 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2153 GL_DepthMask(false);
2154 memset(&m, 0, sizeof(m));
2155 m.tex[0] = R_GetTexture(texture->skin.glow);
2156 m.texmatrix[0] = texture->currenttexmatrix;
2157 m.pointer_color = varray_color4f;
2162 a = texture->currentalpha;
2163 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2164 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2166 surface = texturesurfacelist[texturesurfaceindex];
2167 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2168 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2169 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2170 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2171 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2172 GL_LockArrays(0, 0);
2177 // if this is opaque use alpha blend which will darken the earlier
2180 // if this is an alpha blended material, all the earlier passes
2181 // were darkened by fog already, so we only need to add the fog
2182 // color ontop through the fog mask texture
2184 // if this is an additive blended material, all the earlier passes
2185 // were darkened by fog already, and we should not add fog color
2186 // (because the background was not darkened, there is no fog color
2187 // that was lost behind it).
2189 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2191 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2192 GL_DepthMask(false);
2193 memset(&m, 0, sizeof(m));
2194 m.tex[0] = R_GetTexture(texture->skin.fog);
2195 m.texmatrix[0] = texture->currenttexmatrix;
2200 a = texture->currentalpha;
2201 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2202 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2204 surface = texturesurfacelist[texturesurfaceindex];
2205 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2206 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2207 R_Mesh_ColorPointer(varray_color4f);
2208 //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);
2209 if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2211 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)
2213 VectorSubtract(v, modelorg, diff);
2214 f = exp(fogdensity/DotProduct(diff, diff));
2218 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * f * a;
2223 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)
2225 VectorSubtract(v, modelorg, diff);
2226 f = exp(fogdensity/DotProduct(diff, diff));
2233 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2234 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2235 GL_LockArrays(0, 0);
2239 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2240 qglEnable(GL_CULL_FACE);
2243 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2245 const entity_render_t *ent = calldata1;
2246 const msurface_t *surface = ent->model->data_surfaces + calldata2;
2250 texture = surface->texture;
2251 if (texture->basematerialflags & MATERIALFLAG_SKY)
2252 return; // transparent sky is too difficult
2253 R_UpdateTextureInfo(ent, texture);
2255 R_Mesh_Matrix(&ent->matrix);
2256 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2257 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2260 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2262 int texturesurfaceindex;
2263 const msurface_t *surface;
2264 vec3_t tempcenter, center;
2265 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2267 // drawing sky transparently would be too difficult
2268 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2270 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2272 surface = texturesurfacelist[texturesurfaceindex];
2273 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2274 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2275 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2276 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2277 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2282 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2285 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2286 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2288 int i, j, f, flagsmask;
2289 msurface_t *surface, **surfacechain;
2290 texture_t *t, *texture;
2291 model_t *model = ent->model;
2293 const int maxsurfacelist = 1024;
2294 int numsurfacelist = 0;
2295 const msurface_t *surfacelist[1024];
2298 R_Mesh_Matrix(&ent->matrix);
2299 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2301 // update light styles
2302 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2304 for (i = 0;i < model->brushq1.light_styles;i++)
2306 if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
2308 model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
2309 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2310 for (;(surface = *surfacechain);surfacechain++)
2311 surface->cached_dlight = true;
2316 R_UpdateAllTextureInfo(ent);
2317 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2322 if (ent == r_refdef.worldentity)
2324 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2326 if (!r_worldsurfacevisible[j])
2328 if (t != surface->texture)
2332 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2335 t = surface->texture;
2336 texture = t->currentframe;
2337 f = texture->currentmaterialflags & flagsmask;
2339 if (f && surface->num_triangles)
2341 // if lightmap parameters changed, rebuild lightmap texture
2342 if (surface->cached_dlight && surface->lightmapinfo->samples)
2343 R_BuildLightMap(ent, surface);
2344 // add face to draw list
2345 surfacelist[numsurfacelist++] = surface;
2346 if (numsurfacelist >= maxsurfacelist)
2348 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2356 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2358 if (t != surface->texture)
2362 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2365 t = surface->texture;
2366 texture = t->currentframe;
2367 f = texture->currentmaterialflags & flagsmask;
2369 if (f && surface->num_triangles)
2371 // if lightmap parameters changed, rebuild lightmap texture
2372 if (surface->cached_dlight && surface->lightmapinfo->samples)
2373 R_BuildLightMap(ent, surface);
2374 // add face to draw list
2375 surfacelist[numsurfacelist++] = surface;
2376 if (numsurfacelist >= maxsurfacelist)
2378 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2385 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);