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];
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 void R_BuildBlankTextures(void)
274 data[0] = 128; // normal X
275 data[1] = 128; // normal Y
276 data[2] = 255; // normal Z
277 data[3] = 128; // height
278 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
283 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
288 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
291 static void R_BuildNoTexture(void)
294 qbyte pix[16][16][4];
295 // this makes a light grey/dark grey checkerboard texture
296 for (y = 0;y < 16;y++)
298 for (x = 0;x < 16;x++)
300 if ((y < 8) ^ (x < 8))
316 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
319 static void R_BuildWhiteCube(void)
322 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
323 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
324 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
325 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
326 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
327 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
328 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
331 static void R_BuildNormalizationCube(void)
335 vec_t s, t, intensity;
337 qbyte data[6][NORMSIZE][NORMSIZE][4];
338 for (side = 0;side < 6;side++)
340 for (y = 0;y < NORMSIZE;y++)
342 for (x = 0;x < NORMSIZE;x++)
344 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
345 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
379 intensity = 127.0f / sqrt(DotProduct(v, v));
380 data[side][y][x][0] = 128.0f + intensity * v[0];
381 data[side][y][x][1] = 128.0f + intensity * v[1];
382 data[side][y][x][2] = 128.0f + intensity * v[2];
383 data[side][y][x][3] = 255;
387 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
390 void gl_main_start(void)
392 r_main_texturepool = R_AllocTexturePool();
393 r_bloom_texture_screen = NULL;
394 r_bloom_texture_bloom = NULL;
395 R_BuildBlankTextures();
397 R_BuildDetailTextures();
398 if (gl_texturecubemap)
401 R_BuildNormalizationCube();
405 void gl_main_shutdown(void)
407 R_FreeTexturePool(&r_main_texturepool);
408 r_bloom_texture_screen = NULL;
409 r_bloom_texture_bloom = NULL;
410 r_texture_blanknormalmap = NULL;
411 r_texture_white = NULL;
412 r_texture_black = NULL;
413 r_texture_whitecube = NULL;
414 r_texture_normalizationcube = NULL;
417 extern void CL_ParseEntityLump(char *entitystring);
418 void gl_main_newmap(void)
420 // FIXME: move this code to client
422 char *entities, entname[MAX_QPATH];
426 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
427 l = (int)strlen(entname) - 4;
428 if (l >= 0 && !strcmp(entname + l, ".bsp"))
430 strcpy(entname + l, ".ent");
431 if ((entities = FS_LoadFile(entname, tempmempool, true)))
433 CL_ParseEntityLump(entities);
438 if (cl.worldmodel->brush.entities)
439 CL_ParseEntityLump(cl.worldmodel->brush.entities);
443 void GL_Main_Init(void)
445 Matrix4x4_CreateIdentity(&r_identitymatrix);
446 // FIXME: move this to client?
448 Cvar_RegisterVariable(&r_showtris);
449 Cvar_RegisterVariable(&r_drawentities);
450 Cvar_RegisterVariable(&r_drawviewmodel);
451 Cvar_RegisterVariable(&r_speeds);
452 Cvar_RegisterVariable(&r_fullbrights);
453 Cvar_RegisterVariable(&r_wateralpha);
454 Cvar_RegisterVariable(&r_dynamic);
455 Cvar_RegisterVariable(&r_fullbright);
456 Cvar_RegisterVariable(&r_textureunits);
457 Cvar_RegisterVariable(&r_lerpsprites);
458 Cvar_RegisterVariable(&r_lerpmodels);
459 Cvar_RegisterVariable(&r_waterscroll);
460 Cvar_RegisterVariable(&r_drawcollisionbrushes);
461 Cvar_RegisterVariable(&r_bloom);
462 Cvar_RegisterVariable(&r_bloom_intensity);
463 Cvar_RegisterVariable(&r_bloom_blur);
464 Cvar_RegisterVariable(&r_bloom_resolution);
465 Cvar_RegisterVariable(&r_bloom_power);
466 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
467 Cvar_RegisterVariable(&developer_texturelogging);
468 Cvar_RegisterVariable(&gl_lightmaps);
469 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
470 Cvar_SetValue("r_fullbrights", 0);
471 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
474 static vec3_t r_farclip_origin;
475 static vec3_t r_farclip_direction;
476 static vec_t r_farclip_directiondist;
477 static vec_t r_farclip_meshfarclip;
478 static int r_farclip_directionbit0;
479 static int r_farclip_directionbit1;
480 static int r_farclip_directionbit2;
482 // enlarge farclip to accomodate box
483 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
486 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
487 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
488 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
489 if (r_farclip_meshfarclip < d)
490 r_farclip_meshfarclip = d;
493 // return farclip value
494 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
498 VectorCopy(origin, r_farclip_origin);
499 VectorCopy(direction, r_farclip_direction);
500 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
501 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
502 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
503 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
504 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
506 if (r_refdef.worldmodel)
507 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
508 for (i = 0;i < r_refdef.numentities;i++)
509 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
511 return r_farclip_meshfarclip - r_farclip_directiondist;
514 extern void R_Textures_Init(void);
515 extern void GL_Draw_Init(void);
516 extern void GL_Main_Init(void);
517 extern void R_Shadow_Init(void);
518 extern void R_Sky_Init(void);
519 extern void GL_Surf_Init(void);
520 extern void R_Crosshairs_Init(void);
521 extern void R_Light_Init(void);
522 extern void R_Particles_Init(void);
523 extern void R_Explosion_Init(void);
524 extern void gl_backend_init(void);
525 extern void Sbar_Init(void);
526 extern void R_LightningBeams_Init(void);
527 extern void Mod_RenderInit(void);
529 void Render_Init(void)
545 R_LightningBeams_Init();
554 extern char *ENGINE_EXTENSIONS;
557 VID_CheckExtensions();
559 // LordHavoc: report supported extensions
560 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
562 // clear to black (loading plaque will be seen over this)
563 qglClearColor(0,0,0,1);
564 qglClear(GL_COLOR_BUFFER_BIT);
567 int R_CullBox(const vec3_t mins, const vec3_t maxs)
571 for (i = 0;i < 4;i++)
578 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
582 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
586 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
590 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
594 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
598 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
602 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
606 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
614 //==================================================================================
616 static void R_MarkEntities (void)
619 entity_render_t *ent;
621 if (!r_drawentities.integer)
624 r_refdef.worldentity->visframe = r_framecount;
625 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
626 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
628 // worldmodel can check visibility
629 for (i = 0;i < r_refdef.numentities;i++)
631 ent = r_refdef.entities[i];
632 Mod_CheckLoaded(ent->model);
633 // some of the renderer still relies on origin...
634 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
635 // some of the renderer still relies on scale...
636 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
637 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)))
639 R_UpdateEntLights(ent);
640 ent->visframe = r_framecount;
646 // no worldmodel or it can't check visibility
647 for (i = 0;i < r_refdef.numentities;i++)
649 ent = r_refdef.entities[i];
650 Mod_CheckLoaded(ent->model);
651 // some of the renderer still relies on origin...
652 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
653 // some of the renderer still relies on scale...
654 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
655 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
657 R_UpdateEntLights(ent);
658 ent->visframe = r_framecount;
664 // only used if skyrendermasked, and normally returns false
665 int R_DrawBrushModelsSky (void)
668 entity_render_t *ent;
670 if (!r_drawentities.integer)
674 for (i = 0;i < r_refdef.numentities;i++)
676 ent = r_refdef.entities[i];
677 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
679 ent->model->DrawSky(ent);
686 void R_DrawNoModel(entity_render_t *ent);
687 void R_DrawModels(void)
690 entity_render_t *ent;
692 if (!r_drawentities.integer)
695 for (i = 0;i < r_refdef.numentities;i++)
697 ent = r_refdef.entities[i];
698 if (ent->visframe == r_framecount)
700 if (ent->model && ent->model->Draw != NULL)
701 ent->model->Draw(ent);
708 static void R_SetFrustum(void)
710 // break apart the view matrix into vectors for various purposes
711 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
712 VectorNegate(r_viewleft, r_viewright);
714 // LordHavoc: note to all quake engine coders, the special case for 90
715 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
718 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
719 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
720 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
721 PlaneClassify(&frustum[0]);
723 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
724 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
725 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
726 PlaneClassify(&frustum[1]);
728 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
729 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
730 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
731 PlaneClassify(&frustum[2]);
733 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
734 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
735 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
736 PlaneClassify(&frustum[3]);
739 VectorCopy(r_viewforward, frustum[4].normal);
740 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
741 PlaneClassify(&frustum[4]);
744 static void R_BlendView(void)
748 if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
751 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
754 R_Mesh_Matrix(&r_identitymatrix);
755 // vertex coordinates for a quad that covers the screen exactly
756 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
757 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
758 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
759 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
760 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)
762 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
763 float xoffset, yoffset, r;
765 // set the (poorly named) screenwidth and screenheight variables to
766 // a power of 2 at least as large as the screen, these will define the
767 // size of the texture to allocate
768 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
769 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
770 // allocate textures as needed
771 if (!r_bloom_texture_screen)
772 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
773 if (!r_bloom_texture_bloom)
774 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
775 // set bloomwidth and bloomheight to the bloom resolution that will be
776 // used (often less than the screen resolution for faster rendering)
777 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
778 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
779 // set up a texcoord array for the full resolution screen image
780 // (we have to keep this around to copy back during final render)
781 varray_texcoord2f[0][0] = 0;
782 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
783 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
784 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
785 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
786 varray_texcoord2f[0][5] = 0;
787 varray_texcoord2f[0][6] = 0;
788 varray_texcoord2f[0][7] = 0;
789 // set up a texcoord array for the reduced resolution bloom image
790 // (which will be additive blended over the screen image)
791 varray_texcoord2f[1][0] = 0;
792 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
793 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
794 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
795 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
796 varray_texcoord2f[1][5] = 0;
797 varray_texcoord2f[1][6] = 0;
798 varray_texcoord2f[1][7] = 0;
799 memset(&m, 0, sizeof(m));
800 m.pointer_vertex = varray_vertex3f;
801 m.pointer_texcoord[0] = varray_texcoord2f[0];
802 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
804 // copy view into the full resolution screen image texture
806 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
808 c_bloomcopypixels += r_view_width * r_view_height;
809 // now scale it down to the bloom size and raise to a power of itself
810 // to darken it (this leaves the really bright stuff bright, and
811 // everything else becomes very dark)
812 // TODO: optimize with multitexture or GLSL
813 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
814 GL_BlendFunc(GL_ONE, GL_ZERO);
815 GL_Color(1, 1, 1, 1);
816 R_Mesh_Draw(0, 4, 2, polygonelements);
818 c_bloomdrawpixels += bloomwidth * bloomheight;
819 // render multiple times with a multiply blendfunc to raise to a power
820 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
821 for (x = 1;x < r_bloom_power.integer;x++)
823 R_Mesh_Draw(0, 4, 2, polygonelements);
825 c_bloomdrawpixels += bloomwidth * bloomheight;
827 // we now have a darkened bloom image in the framebuffer, copy it into
828 // the bloom image texture for more processing
829 memset(&m, 0, sizeof(m));
830 m.pointer_vertex = varray_vertex3f;
831 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
832 m.pointer_texcoord[0] = varray_texcoord2f[2];
835 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
837 c_bloomcopypixels += bloomwidth * bloomheight;
838 // blend on at multiple vertical offsets to achieve a vertical blur
839 // TODO: do offset blends using GLSL
840 range = r_bloom_blur.integer * bloomwidth / 320;
841 GL_BlendFunc(GL_ONE, GL_ZERO);
842 for (x = -range;x <= range;x++)
844 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
845 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
846 // compute a texcoord array with the specified x and y offset
847 varray_texcoord2f[2][0] = xoffset+0;
848 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
849 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
850 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
851 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
852 varray_texcoord2f[2][5] = yoffset+0;
853 varray_texcoord2f[2][6] = xoffset+0;
854 varray_texcoord2f[2][7] = yoffset+0;
855 // this r value looks like a 'dot' particle, fading sharply to
856 // black at the edges
857 // (probably not realistic but looks good enough)
858 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
861 GL_Color(r, r, r, 1);
862 R_Mesh_Draw(0, 4, 2, polygonelements);
864 c_bloomdrawpixels += bloomwidth * bloomheight;
865 GL_BlendFunc(GL_ONE, GL_ONE);
867 // copy the vertically blurred bloom view to a texture
869 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
871 c_bloomcopypixels += bloomwidth * bloomheight;
872 // blend the vertically blurred image at multiple offsets horizontally
873 // to finish the blur effect
874 // TODO: do offset blends using GLSL
875 range = r_bloom_blur.integer * bloomwidth / 320;
876 GL_BlendFunc(GL_ONE, GL_ZERO);
877 for (x = -range;x <= range;x++)
879 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
880 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
881 // compute a texcoord array with the specified x and y offset
882 varray_texcoord2f[2][0] = xoffset+0;
883 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
884 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
885 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
886 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
887 varray_texcoord2f[2][5] = yoffset+0;
888 varray_texcoord2f[2][6] = xoffset+0;
889 varray_texcoord2f[2][7] = yoffset+0;
890 // this r value looks like a 'dot' particle, fading sharply to
891 // black at the edges
892 // (probably not realistic but looks good enough)
893 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
896 GL_Color(r, r, r, 1);
897 R_Mesh_Draw(0, 4, 2, polygonelements);
899 c_bloomdrawpixels += bloomwidth * bloomheight;
900 GL_BlendFunc(GL_ONE, GL_ONE);
902 // copy the blurred bloom view to a texture
904 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
906 c_bloomcopypixels += bloomwidth * bloomheight;
907 // go back to full view area
908 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
909 // put the original screen image back in place and blend the bloom
911 memset(&m, 0, sizeof(m));
912 m.pointer_vertex = varray_vertex3f;
913 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
914 m.pointer_texcoord[0] = varray_texcoord2f[0];
916 dobloomblend = false;
918 // do both in one pass if possible
919 if (r_textureunits.integer >= 2 && gl_combine.integer)
921 dobloomblend = false;
922 m.texcombinergb[1] = GL_ADD;
923 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
924 m.pointer_texcoord[1] = varray_texcoord2f[1];
930 GL_BlendFunc(GL_ONE, GL_ZERO);
932 R_Mesh_Draw(0, 4, 2, polygonelements);
934 c_bloomdrawpixels += r_view_width * r_view_height;
935 // now blend on the bloom texture if multipass
938 memset(&m, 0, sizeof(m));
939 m.pointer_vertex = varray_vertex3f;
940 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
941 m.pointer_texcoord[0] = varray_texcoord2f[1];
943 GL_BlendFunc(GL_ONE, GL_ONE);
945 R_Mesh_Draw(0, 4, 2, polygonelements);
947 c_bloomdrawpixels += r_view_width * r_view_height;
950 if (r_refdef.viewblend[3] >= 0.01f)
952 // apply a color tint to the whole view
953 memset(&m, 0, sizeof(m));
954 m.pointer_vertex = varray_vertex3f;
956 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
957 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
958 R_Mesh_Draw(0, 4, 2, polygonelements);
962 void R_RenderScene(void);
964 matrix4x4_t r_waterscrollmatrix;
971 void R_RenderView(void)
973 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
974 return; //Host_Error ("R_RenderView: NULL worldmodel");
976 r_view_width = bound(0, r_refdef.width, vid.width);
977 r_view_height = bound(0, r_refdef.height, vid.height);
979 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
980 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
982 r_view_fov_x = bound(1, r_refdef.fov_x, 170);
983 r_view_fov_y = bound(1, r_refdef.fov_y, 170);
984 r_view_matrix = r_refdef.viewentitymatrix;
985 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
986 r_rtworld = r_shadow_realtime_world.integer;
987 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
988 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
989 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
990 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
992 // GL is weird because it's bottom to top, r_view_y is top to bottom
993 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
994 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
995 GL_ScissorTest(true);
1001 R_TimeReport("setup");
1003 qglDepthFunc(GL_LEQUAL);
1004 qglPolygonOffset(0, 0);
1005 qglEnable(GL_POLYGON_OFFSET_FILL);
1009 qglPolygonOffset(0, 0);
1010 qglDisable(GL_POLYGON_OFFSET_FILL);
1013 R_TimeReport("blendview");
1015 GL_Scissor(0, 0, vid.width, vid.height);
1016 GL_ScissorTest(false);
1019 extern void R_DrawLightningBeams (void);
1020 void R_RenderScene(void)
1022 // don't let sound skip if going slow
1023 if (r_refdef.extraupdate)
1028 R_MeshQueue_BeginScene();
1030 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1034 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1035 if (r_rtworldshadows || r_rtdlightshadows)
1036 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
1038 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
1040 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1042 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);
1046 R_WorldVisibility();
1047 R_TimeReport("worldvis");
1050 R_TimeReport("markentity");
1052 R_Shadow_UpdateWorldLightSelection();
1054 // don't let sound skip if going slow
1055 if (r_refdef.extraupdate)
1058 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1059 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1061 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1062 R_TimeReport("worldsky");
1065 if (R_DrawBrushModelsSky())
1066 R_TimeReport("bmodelsky");
1068 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1069 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1071 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1072 R_TimeReport("world");
1075 // don't let sound skip if going slow
1076 if (r_refdef.extraupdate)
1079 GL_ShowTrisColor(0, 0.015, 0, 1);
1082 R_TimeReport("models");
1084 // don't let sound skip if going slow
1085 if (r_refdef.extraupdate)
1088 GL_ShowTrisColor(0, 0, 0.033, 1);
1089 R_ShadowVolumeLighting(false);
1090 R_TimeReport("rtlights");
1092 // don't let sound skip if going slow
1093 if (r_refdef.extraupdate)
1096 GL_ShowTrisColor(0.1, 0, 0, 1);
1098 R_DrawLightningBeams();
1099 R_TimeReport("lightning");
1102 R_TimeReport("particles");
1105 R_TimeReport("explosions");
1107 R_MeshQueue_RenderTransparent();
1108 R_TimeReport("drawtrans");
1111 R_TimeReport("coronas");
1113 R_DrawWorldCrosshair();
1114 R_TimeReport("crosshair");
1116 R_MeshQueue_Render();
1117 R_MeshQueue_EndScene();
1119 if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1121 R_ShadowVolumeLighting(true);
1122 R_TimeReport("visiblevolume");
1125 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1127 // don't let sound skip if going slow
1128 if (r_refdef.extraupdate)
1133 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1136 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1138 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1139 GL_DepthMask(false);
1141 R_Mesh_Matrix(&r_identitymatrix);
1143 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1144 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1145 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1146 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1147 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1148 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1149 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1150 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1151 R_FillColors(color, 8, cr, cg, cb, ca);
1154 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1156 VectorSubtract(v, r_vieworigin, diff);
1157 f2 = exp(fogdensity/DotProduct(diff, diff));
1159 c[0] = c[0] * f1 + fogcolor[0] * f2;
1160 c[1] = c[1] * f1 + fogcolor[1] * f2;
1161 c[2] = c[2] * f1 + fogcolor[2] * f2;
1164 memset(&m, 0, sizeof(m));
1165 m.pointer_vertex = vertex3f;
1166 m.pointer_color = color;
1172 int nomodelelements[24] =
1184 float nomodelvertex3f[6*3] =
1194 float nomodelcolor4f[6*4] =
1196 0.0f, 0.0f, 0.5f, 1.0f,
1197 0.0f, 0.0f, 0.5f, 1.0f,
1198 0.0f, 0.5f, 0.0f, 1.0f,
1199 0.0f, 0.5f, 0.0f, 1.0f,
1200 0.5f, 0.0f, 0.0f, 1.0f,
1201 0.5f, 0.0f, 0.0f, 1.0f
1204 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1206 const entity_render_t *ent = calldata1;
1208 float f1, f2, *c, diff[3];
1211 R_Mesh_Matrix(&ent->matrix);
1213 memset(&m, 0, sizeof(m));
1214 m.pointer_vertex = nomodelvertex3f;
1216 if (ent->flags & EF_ADDITIVE)
1218 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1219 GL_DepthMask(false);
1221 else if (ent->alpha < 1)
1223 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1224 GL_DepthMask(false);
1228 GL_BlendFunc(GL_ONE, GL_ZERO);
1231 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1234 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1235 m.pointer_color = color4f;
1236 VectorSubtract(ent->origin, r_vieworigin, diff);
1237 f2 = exp(fogdensity/DotProduct(diff, diff));
1239 for (i = 0, c = color4f;i < 6;i++, c += 4)
1241 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1242 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1243 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1247 else if (ent->alpha != 1)
1249 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1250 m.pointer_color = color4f;
1251 for (i = 0, c = color4f;i < 6;i++, c += 4)
1255 m.pointer_color = nomodelcolor4f;
1257 R_Mesh_Draw(0, 6, 8, nomodelelements);
1260 void R_DrawNoModel(entity_render_t *ent)
1262 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1263 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1265 // R_DrawNoModelCallback(ent, 0);
1268 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1270 vec3_t right1, right2, diff, normal;
1272 VectorSubtract (org2, org1, normal);
1274 // calculate 'right' vector for start
1275 VectorSubtract (r_vieworigin, org1, diff);
1276 CrossProduct (normal, diff, right1);
1277 VectorNormalize (right1);
1279 // calculate 'right' vector for end
1280 VectorSubtract (r_vieworigin, org2, diff);
1281 CrossProduct (normal, diff, right2);
1282 VectorNormalize (right2);
1284 vert[ 0] = org1[0] + width * right1[0];
1285 vert[ 1] = org1[1] + width * right1[1];
1286 vert[ 2] = org1[2] + width * right1[2];
1287 vert[ 3] = org1[0] - width * right1[0];
1288 vert[ 4] = org1[1] - width * right1[1];
1289 vert[ 5] = org1[2] - width * right1[2];
1290 vert[ 6] = org2[0] - width * right2[0];
1291 vert[ 7] = org2[1] - width * right2[1];
1292 vert[ 8] = org2[2] - width * right2[2];
1293 vert[ 9] = org2[0] + width * right2[0];
1294 vert[10] = org2[1] + width * right2[1];
1295 vert[11] = org2[2] + width * right2[2];
1298 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1300 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)
1307 VectorSubtract(origin, r_vieworigin, diff);
1308 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1311 R_Mesh_Matrix(&r_identitymatrix);
1312 GL_BlendFunc(blendfunc1, blendfunc2);
1313 GL_DepthMask(false);
1314 GL_DepthTest(!depthdisable);
1316 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1317 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1318 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1319 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1320 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1321 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1322 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1323 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1324 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1325 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1326 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1327 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1329 memset(&m, 0, sizeof(m));
1330 m.tex[0] = R_GetTexture(texture);
1331 m.pointer_texcoord[0] = spritetexcoord2f;
1332 m.pointer_vertex = varray_vertex3f;
1334 GL_Color(cr, cg, cb, ca);
1335 R_Mesh_Draw(0, 4, 2, polygonelements);
1338 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1342 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1343 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1345 if (i == mesh->numvertices)
1347 if (mesh->numvertices < mesh->maxvertices)
1349 VectorCopy(v, vertex3f);
1350 mesh->numvertices++;
1352 return mesh->numvertices;
1358 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1362 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1363 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1364 e = mesh->element3i + mesh->numtriangles * 3;
1365 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1367 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1368 if (mesh->numtriangles < mesh->maxtriangles)
1373 mesh->numtriangles++;
1375 element[1] = element[2];
1379 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1381 int planenum, planenum2;
1384 mplane_t *plane, *plane2;
1385 float temppoints[2][256*3];
1386 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1390 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1391 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1393 if (planenum2 == planenum)
1395 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);
1398 if (tempnumpoints < 3)
1400 // generate elements forming a triangle fan for this polygon
1401 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1405 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1407 texture_t *texture = t;
1408 model_t *model = ent->model;
1409 int s = ent->skinnum;
1410 if ((unsigned int)s >= (unsigned int)model->numskins)
1414 if (model->skinscenes)
1416 if (model->skinscenes[s].framecount > 1)
1417 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1419 s = model->skinscenes[s].firstframe;
1422 t = t + s * model->num_surfaces;
1424 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];
1425 texture->currentframe = t;
1426 t->currentmaterialflags = t->basematerialflags;
1427 t->currentalpha = ent->alpha;
1428 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1429 t->currentalpha *= r_wateralpha.value;
1430 if (!(ent->flags & RENDER_LIGHT))
1431 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1432 if (ent->effects & EF_ADDITIVE)
1433 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1434 else if (t->currentalpha < 1)
1435 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1436 if (ent->effects & EF_NODEPTHTEST)
1437 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1438 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1439 t->currenttexmatrix = r_waterscrollmatrix;
1441 t->currenttexmatrix = r_identitymatrix;
1444 void R_UpdateAllTextureInfo(entity_render_t *ent)
1448 for (i = 0;i < ent->model->num_textures;i++)
1449 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1452 float *rsurface_vertex3f;
1453 float *rsurface_svector3f;
1454 float *rsurface_tvector3f;
1455 float *rsurface_normal3f;
1456 float *rsurface_lightmapcolor4f;
1458 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1461 float center[3], forward[3], right[3], up[3], v[4][3];
1462 matrix4x4_t matrix1, imatrix1;
1463 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1465 rsurface_vertex3f = varray_vertex3f;
1466 rsurface_svector3f = NULL;
1467 rsurface_tvector3f = NULL;
1468 rsurface_normal3f = NULL;
1469 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1473 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1474 rsurface_svector3f = surface->groupmesh->data_svector3f;
1475 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1476 rsurface_normal3f = surface->groupmesh->data_normal3f;
1478 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1480 if (!rsurface_svector3f)
1482 rsurface_svector3f = varray_svector3f;
1483 rsurface_tvector3f = varray_tvector3f;
1484 rsurface_normal3f = varray_normal3f;
1485 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);
1487 // a single autosprite surface can contain multiple sprites...
1488 VectorClear(forward);
1490 VectorSet(up, 0, 0, 1);
1491 for (j = 0;j < surface->num_vertices - 3;j += 4)
1493 VectorClear(center);
1494 for (i = 0;i < 4;i++)
1495 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1496 VectorScale(center, 0.25f, center);
1497 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1498 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);
1499 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1500 for (i = 0;i < 4;i++)
1501 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1502 forward[0] = modelorg[0] - center[0];
1503 forward[1] = modelorg[1] - center[1];
1504 VectorNormalize(forward);
1505 right[0] = forward[1];
1506 right[1] = -forward[0];
1507 for (i = 0;i < 4;i++)
1508 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1510 rsurface_vertex3f = varray_vertex3f;
1511 rsurface_svector3f = NULL;
1512 rsurface_tvector3f = NULL;
1513 rsurface_normal3f = NULL;
1515 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1517 if (!rsurface_svector3f)
1519 rsurface_svector3f = varray_svector3f;
1520 rsurface_tvector3f = varray_tvector3f;
1521 rsurface_normal3f = varray_normal3f;
1522 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);
1524 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1525 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1526 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1527 // a single autosprite surface can contain multiple sprites...
1528 for (j = 0;j < surface->num_vertices - 3;j += 4)
1530 VectorClear(center);
1531 for (i = 0;i < 4;i++)
1532 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1533 VectorScale(center, 0.25f, center);
1534 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1535 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);
1536 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1537 for (i = 0;i < 4;i++)
1538 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1539 for (i = 0;i < 4;i++)
1540 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1542 rsurface_vertex3f = varray_vertex3f;
1543 rsurface_svector3f = NULL;
1544 rsurface_tvector3f = NULL;
1545 rsurface_normal3f = NULL;
1547 R_Mesh_VertexPointer(rsurface_vertex3f);
1550 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)
1558 vec4_t ambientcolor4f;
1559 vec3_t diffusecolor;
1560 vec3_t diffusenormal;
1561 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1563 rsurface_lightmapcolor4f = varray_color4f;
1564 if (rsurface_normal3f == NULL)
1566 rsurface_normal3f = varray_normal3f;
1567 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);
1569 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);
1578 r = ambientcolor4f[0];
1579 g = ambientcolor4f[1];
1580 b = ambientcolor4f[2];
1581 a = ambientcolor4f[3];
1582 rsurface_lightmapcolor4f = NULL;
1585 else if (lightmode >= 1)
1587 if (surface->lightmapinfo)
1589 rsurface_lightmapcolor4f = varray_color4f;
1590 for (i = 0, c = rsurface_lightmapcolor4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1592 const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1593 float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1594 VectorScale(lm, scale, c);
1595 if (surface->lightmapinfo->styles[1] != 255)
1597 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1599 scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1600 VectorMA(c, scale, lm, c);
1601 if (surface->lightmapinfo->styles[2] != 255)
1604 scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1605 VectorMA(c, scale, lm, c);
1606 if (surface->lightmapinfo->styles[3] != 255)
1609 scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1610 VectorMA(c, scale, lm, c);
1617 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1620 rsurface_lightmapcolor4f = NULL;
1623 if (rsurface_lightmapcolor4f)
1625 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)
1627 VectorSubtract(v, modelorg, diff);
1628 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1637 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)
1639 VectorSubtract(v, modelorg, diff);
1640 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1647 rsurface_lightmapcolor4f = varray_color4f;
1649 if (applycolor && rsurface_lightmapcolor4f)
1651 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)
1659 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1660 GL_Color(r, g, b, a);
1664 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1667 int texturesurfaceindex;
1671 float colorpants[3], colorshirt[3];
1672 float f, r, g, b, a, colorscale;
1673 const msurface_t *surface;
1674 qboolean dolightmap;
1679 qboolean fogallpasses;
1682 qboolean dofullbrightpants;
1683 qboolean dofullbrightshirt;
1684 qboolean applycolor;
1685 qboolean lightmode = 0;
1686 rtexture_t *basetexture;
1688 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1690 c_faces += texturenumsurfaces;
1691 // FIXME: identify models using a better check than ent->model->shadowmesh
1692 if (!(ent->effects & EF_FULLBRIGHT) && !ent->model->brush.shadowmesh)
1694 // gl_lightmaps debugging mode skips normal texturing
1695 if (gl_lightmaps.integer)
1697 GL_BlendFunc(GL_ONE, GL_ZERO);
1700 qglDisable(GL_CULL_FACE);
1701 GL_Color(1, 1, 1, 1);
1702 memset(&m, 0, sizeof(m));
1704 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1706 surface = texturesurfacelist[texturesurfaceindex];
1707 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1708 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1709 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1710 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, lightmode ? lightmode : !surface->lightmaptexture, false, false);
1711 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1712 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1713 GL_LockArrays(0, 0);
1715 qglEnable(GL_CULL_FACE);
1718 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1719 GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT));
1720 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
1721 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1722 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
1723 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1725 GL_BlendFunc(GL_ONE, GL_ZERO);
1726 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1727 qglDisable(GL_CULL_FACE);
1728 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
1732 skyrendernow = false;
1733 if (skyrendermasked)
1736 // LordHavoc: HalfLife maps have freaky skypolys...
1737 //if (!ent->model->brush.ishlbsp)
1739 R_Mesh_Matrix(&ent->matrix);
1740 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
1741 if (skyrendermasked)
1743 // depth-only (masking)
1744 GL_ColorMask(0,0,0,0);
1745 // just to make sure that braindead drivers don't draw anything
1746 // despite that colormask...
1747 GL_BlendFunc(GL_ZERO, GL_ONE);
1752 GL_BlendFunc(GL_ONE, GL_ZERO);
1756 memset(&m, 0, sizeof(m));
1758 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1760 surface = texturesurfacelist[texturesurfaceindex];
1761 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1762 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1763 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1764 GL_LockArrays(0, 0);
1766 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1769 else if (texture->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1771 // normal surface (wall or water)
1772 dolightmap = !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT);
1773 doambient = r_ambient.value >= (1/64.0f);
1774 dodetail = r_detailtextures.integer && texture->skin.detail != NULL && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
1775 doglow = texture->skin.glow != NULL;
1776 dofogpass = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD);
1777 fogallpasses = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
1778 if (ent->colormap >= 0)
1782 basetexture = texture->skin.base;
1783 dopants = texture->skin.pants != NULL;
1784 doshirt = texture->skin.shirt != NULL;
1785 // 128-224 are backwards ranges
1786 b = (ent->colormap & 0xF) << 4;b += (b >= 128 && b < 224) ? 4 : 12;
1787 dofullbrightpants = b >= 224;
1788 bcolor = (qbyte *) (&palette_complete[b]);
1789 VectorScale(bcolor, (1.0f / 255.0f), colorpants);
1790 // 128-224 are backwards ranges
1791 b = (ent->colormap & 0xF0);b += (b >= 128 && b < 224) ? 4 : 12;
1792 dofullbrightshirt = b >= 224;
1793 bcolor = (qbyte *) (&palette_complete[b]);
1794 VectorScale(bcolor, (1.0f / 255.0f), colorshirt);
1798 basetexture = texture->skin.merged ? texture->skin.merged : texture->skin.base;
1801 dofullbrightshirt = false;
1802 dofullbrightpants = false;
1804 if (dolightmap && r_textureunits.integer >= 2 && gl_combine.integer)
1806 memset(&m, 0, sizeof(m));
1807 m.tex[1] = R_GetTexture(basetexture);
1808 m.texmatrix[1] = texture->currenttexmatrix;
1809 m.texrgbscale[1] = 2;
1810 m.pointer_color = varray_color4f;
1812 // transparent is not affected by r_lightmapintensity
1813 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1814 colorscale = r_lightmapintensity;
1817 // q3bsp has no lightmap updates, so the lightstylevalue that
1818 // would normally be baked into the lightmaptexture must be
1819 // applied to the color
1820 if (ent->model->type == mod_brushq3)
1821 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
1822 r = ent->colormod[0] * colorscale;
1823 g = ent->colormod[1] * colorscale;
1824 b = ent->colormod[2] * colorscale;
1825 a = texture->currentalpha;
1826 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
1827 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1829 surface = texturesurfacelist[texturesurfaceindex];
1830 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1831 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1832 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1833 if (surface->lightmaptexture)
1834 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1836 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1837 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode ? lightmode : !surface->lightmaptexture, applycolor, fogallpasses);
1838 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1839 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1840 GL_LockArrays(0, 0);
1843 else if (dolightmap && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT) && !lightmode)
1846 GL_BlendFunc(GL_ONE, GL_ZERO);
1848 GL_Color(1, 1, 1, 1);
1849 memset(&m, 0, sizeof(m));
1851 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1853 surface = texturesurfacelist[texturesurfaceindex];
1854 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1855 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1856 if (surface->lightmaptexture)
1858 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1859 R_Mesh_ColorPointer(NULL);
1863 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1864 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
1866 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1867 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1868 GL_LockArrays(0, 0);
1870 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1871 GL_DepthMask(false);
1872 GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
1873 memset(&m, 0, sizeof(m));
1874 m.tex[0] = R_GetTexture(basetexture);
1875 m.texmatrix[0] = texture->currenttexmatrix;
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_texcoordtexture2f);
1882 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1883 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1884 GL_LockArrays(0, 0);
1889 memset(&m, 0, sizeof(m));
1890 m.tex[0] = R_GetTexture(basetexture);
1891 m.texmatrix[0] = texture->currenttexmatrix;
1892 m.pointer_color = varray_color4f;
1894 if (gl_combine.integer)
1896 m.texrgbscale[0] = 2;
1899 // transparent is not affected by r_lightmapintensity
1900 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1901 colorscale *= r_lightmapintensity;
1902 // q3bsp has no lightmap updates, so the lightstylevalue that
1903 // would normally be baked into the lightmaptexture must be
1904 // applied to the color
1905 if (dolightmap && ent->model->type == mod_brushq3)
1906 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
1908 r = ent->colormod[0] * colorscale;
1909 g = ent->colormod[1] * colorscale;
1910 b = ent->colormod[2] * colorscale;
1911 a = texture->currentalpha;
1912 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
1915 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1917 surface = texturesurfacelist[texturesurfaceindex];
1918 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1919 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1920 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, fogallpasses);
1921 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1922 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1923 GL_LockArrays(0, 0);
1928 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1930 surface = texturesurfacelist[texturesurfaceindex];
1931 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1932 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1933 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
1934 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1935 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1936 GL_LockArrays(0, 0);
1942 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1943 memset(&m, 0, sizeof(m));
1944 m.tex[0] = R_GetTexture(texture->skin.pants);
1945 m.texmatrix[0] = texture->currenttexmatrix;
1946 m.pointer_color = varray_color4f;
1948 if (gl_combine.integer)
1950 m.texrgbscale[0] = 2;
1953 // transparent is not affected by r_lightmapintensity
1954 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1955 colorscale *= r_lightmapintensity;
1956 // q3bsp has no lightmap updates, so the lightstylevalue that
1957 // would normally be baked into the lightmaptexture must be
1958 // applied to the color
1959 if (dolightmap && !dofullbrightpants && ent->model->type == mod_brushq3)
1960 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
1962 r = ent->colormod[0] * colorpants[0] * colorscale;
1963 g = ent->colormod[1] * colorpants[1] * colorscale;
1964 b = ent->colormod[2] * colorpants[2] * colorscale;
1965 a = texture->currentalpha;
1966 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
1967 if (dolightmap && !dofullbrightpants)
1969 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1971 surface = texturesurfacelist[texturesurfaceindex];
1972 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1973 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1974 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, fogallpasses);
1975 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1976 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1977 GL_LockArrays(0, 0);
1982 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1984 surface = texturesurfacelist[texturesurfaceindex];
1985 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1986 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1987 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
1988 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1989 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1990 GL_LockArrays(0, 0);
1996 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1997 memset(&m, 0, sizeof(m));
1998 m.tex[0] = R_GetTexture(texture->skin.shirt);
1999 m.texmatrix[0] = texture->currenttexmatrix;
2000 m.pointer_color = varray_color4f;
2002 if (gl_combine.integer)
2004 m.texrgbscale[0] = 2;
2007 // transparent is not affected by r_lightmapintensity
2008 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2009 colorscale *= r_lightmapintensity;
2010 // q3bsp has no lightmap updates, so the lightstylevalue that
2011 // would normally be baked into the lightmaptexture must be
2012 // applied to the color
2013 if (dolightmap && !dofullbrightshirt && ent->model->type == mod_brushq3)
2014 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
2016 r = ent->colormod[0] * colorshirt[0] * colorscale;
2017 g = ent->colormod[1] * colorshirt[1] * colorscale;
2018 b = ent->colormod[2] * colorshirt[2] * colorscale;
2019 a = texture->currentalpha;
2020 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2021 if (dolightmap && !dofullbrightshirt)
2023 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2025 surface = texturesurfacelist[texturesurfaceindex];
2026 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2027 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2028 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, fogallpasses);
2029 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2030 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2031 GL_LockArrays(0, 0);
2036 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2038 surface = texturesurfacelist[texturesurfaceindex];
2039 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2040 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2041 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2042 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2043 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2044 GL_LockArrays(0, 0);
2051 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2052 GL_DepthMask(false);
2053 memset(&m, 0, sizeof(m));
2054 m.tex[0] = R_GetTexture(texture->skin.base);
2055 m.texmatrix[0] = texture->currenttexmatrix;
2056 m.pointer_color = varray_color4f;
2058 if (gl_combine.integer && (ent->colormod[0] > 1 || ent->colormod[1] > 1 || ent->colormod[2] > 1))
2060 m.texrgbscale[0] = 4;
2064 colorscale *= r_ambient.value * (1.0f / 64.0f);
2065 r = ent->colormod[0] * colorscale;
2066 g = ent->colormod[1] * colorscale;
2067 b = ent->colormod[2] * colorscale;
2068 a = texture->currentalpha;
2069 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2070 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2072 surface = texturesurfacelist[texturesurfaceindex];
2073 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2074 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2075 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2076 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2077 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2078 GL_LockArrays(0, 0);
2083 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2084 GL_DepthMask(false);
2085 GL_Color(1, 1, 1, 1);
2086 memset(&m, 0, sizeof(m));
2087 m.tex[0] = R_GetTexture(texture->skin.detail);
2089 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2091 surface = texturesurfacelist[texturesurfaceindex];
2092 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2093 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoorddetail2f);
2094 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2095 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2096 GL_LockArrays(0, 0);
2101 // if glow was not already done using multitexture, do it now.
2102 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2103 GL_DepthMask(false);
2104 memset(&m, 0, sizeof(m));
2105 m.tex[0] = R_GetTexture(texture->skin.glow);
2106 m.texmatrix[0] = texture->currenttexmatrix;
2107 m.pointer_color = varray_color4f;
2112 a = texture->currentalpha;
2113 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2114 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2116 surface = texturesurfacelist[texturesurfaceindex];
2117 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2118 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2119 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2120 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2121 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2122 GL_LockArrays(0, 0);
2127 // if this is opaque use alpha blend which will darken the earlier
2130 // if this is an alpha blended material, all the earlier passes
2131 // were darkened by fog already, so we only need to add the fog
2132 // color ontop through the fog mask texture
2134 // if this is an additive blended material, all the earlier passes
2135 // were darkened by fog already, and we should not add fog color
2136 // (because the background was not darkened, there is no fog color
2137 // that was lost behind it).
2139 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2141 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2142 GL_DepthMask(false);
2143 memset(&m, 0, sizeof(m));
2144 m.tex[0] = R_GetTexture(texture->skin.fog);
2145 m.texmatrix[0] = texture->currenttexmatrix;
2150 a = texture->currentalpha;
2151 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2152 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2154 surface = texturesurfacelist[texturesurfaceindex];
2155 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2156 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2157 R_Mesh_ColorPointer(varray_color4f);
2158 //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);
2159 if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2161 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)
2163 VectorSubtract(v, modelorg, diff);
2164 f = exp(fogdensity/DotProduct(diff, diff));
2168 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * f * a;
2173 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)
2175 VectorSubtract(v, modelorg, diff);
2176 f = exp(fogdensity/DotProduct(diff, diff));
2183 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2184 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2185 GL_LockArrays(0, 0);
2189 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2190 qglEnable(GL_CULL_FACE);
2193 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2195 const entity_render_t *ent = calldata1;
2196 const msurface_t *surface = ent->model->data_surfaces + calldata2;
2200 texture = surface->texture;
2201 if (texture->basematerialflags & MATERIALFLAG_SKY)
2202 return; // transparent sky is too difficult
2203 R_UpdateTextureInfo(ent, texture);
2205 R_Mesh_Matrix(&ent->matrix);
2206 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2207 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2210 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2212 int texturesurfaceindex;
2213 const msurface_t *surface;
2214 vec3_t tempcenter, center;
2215 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2217 // drawing sky transparently would be too difficult
2218 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2220 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2222 surface = texturesurfacelist[texturesurfaceindex];
2223 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2224 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2225 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2226 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2227 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2232 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2235 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2236 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2238 int i, j, f, flagsmask;
2239 msurface_t *surface, **surfacechain;
2240 texture_t *t, *texture;
2241 model_t *model = ent->model;
2243 const int maxsurfacelist = 1024;
2244 int numsurfacelist = 0;
2245 const msurface_t *surfacelist[1024];
2248 R_Mesh_Matrix(&ent->matrix);
2249 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2251 // update light styles
2252 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2254 for (i = 0;i < model->brushq1.light_styles;i++)
2256 if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
2258 model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
2259 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2260 for (;(surface = *surfacechain);surfacechain++)
2261 surface->cached_dlight = true;
2266 R_UpdateAllTextureInfo(ent);
2267 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2272 if (ent == r_refdef.worldentity)
2274 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2276 if (!r_worldsurfacevisible[j])
2278 if (t != surface->texture)
2282 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2285 t = surface->texture;
2286 texture = t->currentframe;
2287 f = texture->currentmaterialflags & flagsmask;
2289 if (f && surface->num_triangles)
2291 // if lightmap parameters changed, rebuild lightmap texture
2292 if (surface->cached_dlight && surface->lightmapinfo->samples)
2293 R_BuildLightMap(ent, surface);
2294 // add face to draw list
2295 surfacelist[numsurfacelist++] = surface;
2296 if (numsurfacelist >= maxsurfacelist)
2298 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2306 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2308 if (t != surface->texture)
2312 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2315 t = surface->texture;
2316 texture = t->currentframe;
2317 f = texture->currentmaterialflags & flagsmask;
2319 if (f && surface->num_triangles)
2321 // if lightmap parameters changed, rebuild lightmap texture
2322 if (surface->cached_dlight && surface->lightmapinfo->samples)
2323 R_BuildLightMap(ent, surface);
2324 // add face to draw list
2325 surfacelist[numsurfacelist++] = surface;
2326 if (numsurfacelist >= maxsurfacelist)
2328 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2335 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);