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;
123 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
126 for (i = 0;i < verts;i++)
137 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
140 for (i = 0;i < verts;i++)
152 float fog_density, fog_red, fog_green, fog_blue;
154 qboolean oldgl_fogenable;
155 void R_UpdateFog(void)
157 if (gamemode == GAME_NEHAHRA)
159 if (gl_fogenable.integer)
161 oldgl_fogenable = true;
162 fog_density = gl_fogdensity.value;
163 fog_red = gl_fogred.value;
164 fog_green = gl_foggreen.value;
165 fog_blue = gl_fogblue.value;
167 else if (oldgl_fogenable)
169 oldgl_fogenable = false;
178 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
179 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
180 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
185 fogdensity = -4000.0f / (fog_density * fog_density);
186 // fog color was already set
192 // FIXME: move this to client?
195 if (gamemode == GAME_NEHAHRA)
197 Cvar_Set("gl_fogenable", "0");
198 Cvar_Set("gl_fogdensity", "0.2");
199 Cvar_Set("gl_fogred", "0.3");
200 Cvar_Set("gl_foggreen", "0.3");
201 Cvar_Set("gl_fogblue", "0.3");
203 fog_density = fog_red = fog_green = fog_blue = 0.0f;
206 // FIXME: move this to client?
207 void FOG_registercvars(void)
209 if (gamemode == GAME_NEHAHRA)
211 Cvar_RegisterVariable (&gl_fogenable);
212 Cvar_RegisterVariable (&gl_fogdensity);
213 Cvar_RegisterVariable (&gl_fogred);
214 Cvar_RegisterVariable (&gl_foggreen);
215 Cvar_RegisterVariable (&gl_fogblue);
216 Cvar_RegisterVariable (&gl_fogstart);
217 Cvar_RegisterVariable (&gl_fogend);
221 static void R_BuildBlankTextures(void)
224 data[0] = 128; // normal X
225 data[1] = 128; // normal Y
226 data[2] = 255; // normal Z
227 data[3] = 128; // height
228 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
233 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
238 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
241 static void R_BuildNoTexture(void)
244 qbyte pix[16][16][4];
245 // this makes a light grey/dark grey checkerboard texture
246 for (y = 0;y < 16;y++)
248 for (x = 0;x < 16;x++)
250 if ((y < 8) ^ (x < 8))
266 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
269 static void R_BuildWhiteCube(void)
272 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
273 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
274 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
275 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
276 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
277 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
278 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
281 static void R_BuildNormalizationCube(void)
285 vec_t s, t, intensity;
287 qbyte data[6][NORMSIZE][NORMSIZE][4];
288 for (side = 0;side < 6;side++)
290 for (y = 0;y < NORMSIZE;y++)
292 for (x = 0;x < NORMSIZE;x++)
294 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
295 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
329 intensity = 127.0f / sqrt(DotProduct(v, v));
330 data[side][y][x][0] = 128.0f + intensity * v[0];
331 data[side][y][x][1] = 128.0f + intensity * v[1];
332 data[side][y][x][2] = 128.0f + intensity * v[2];
333 data[side][y][x][3] = 255;
337 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
340 void gl_main_start(void)
342 r_main_texturepool = R_AllocTexturePool();
343 r_bloom_texture_screen = NULL;
344 r_bloom_texture_bloom = NULL;
345 R_BuildBlankTextures();
347 if (gl_texturecubemap)
350 R_BuildNormalizationCube();
354 void gl_main_shutdown(void)
356 R_FreeTexturePool(&r_main_texturepool);
357 r_bloom_texture_screen = NULL;
358 r_bloom_texture_bloom = NULL;
359 r_texture_blanknormalmap = NULL;
360 r_texture_white = NULL;
361 r_texture_black = NULL;
362 r_texture_whitecube = NULL;
363 r_texture_normalizationcube = NULL;
366 extern void CL_ParseEntityLump(char *entitystring);
367 void gl_main_newmap(void)
369 // FIXME: move this code to client
371 char *entities, entname[MAX_QPATH];
375 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
376 l = (int)strlen(entname) - 4;
377 if (l >= 0 && !strcmp(entname + l, ".bsp"))
379 strcpy(entname + l, ".ent");
380 if ((entities = FS_LoadFile(entname, tempmempool, true)))
382 CL_ParseEntityLump(entities);
387 if (cl.worldmodel->brush.entities)
388 CL_ParseEntityLump(cl.worldmodel->brush.entities);
392 void GL_Main_Init(void)
394 Matrix4x4_CreateIdentity(&r_identitymatrix);
395 // FIXME: move this to client?
397 Cvar_RegisterVariable(&r_showtris);
398 Cvar_RegisterVariable(&r_drawentities);
399 Cvar_RegisterVariable(&r_drawviewmodel);
400 Cvar_RegisterVariable(&r_speeds);
401 Cvar_RegisterVariable(&r_fullbrights);
402 Cvar_RegisterVariable(&r_wateralpha);
403 Cvar_RegisterVariable(&r_dynamic);
404 Cvar_RegisterVariable(&r_fullbright);
405 Cvar_RegisterVariable(&r_textureunits);
406 Cvar_RegisterVariable(&r_lerpsprites);
407 Cvar_RegisterVariable(&r_lerpmodels);
408 Cvar_RegisterVariable(&r_waterscroll);
409 Cvar_RegisterVariable(&r_drawcollisionbrushes);
410 Cvar_RegisterVariable(&r_bloom);
411 Cvar_RegisterVariable(&r_bloom_intensity);
412 Cvar_RegisterVariable(&r_bloom_blur);
413 Cvar_RegisterVariable(&r_bloom_resolution);
414 Cvar_RegisterVariable(&r_bloom_power);
415 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
416 Cvar_RegisterVariable(&developer_texturelogging);
417 Cvar_RegisterVariable(&gl_lightmaps);
418 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
419 Cvar_SetValue("r_fullbrights", 0);
420 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
423 static vec3_t r_farclip_origin;
424 static vec3_t r_farclip_direction;
425 static vec_t r_farclip_directiondist;
426 static vec_t r_farclip_meshfarclip;
427 static int r_farclip_directionbit0;
428 static int r_farclip_directionbit1;
429 static int r_farclip_directionbit2;
431 // enlarge farclip to accomodate box
432 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
435 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
436 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
437 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
438 if (r_farclip_meshfarclip < d)
439 r_farclip_meshfarclip = d;
442 // return farclip value
443 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
447 VectorCopy(origin, r_farclip_origin);
448 VectorCopy(direction, r_farclip_direction);
449 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
450 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
451 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
452 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
453 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
455 if (r_refdef.worldmodel)
456 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
457 for (i = 0;i < r_refdef.numentities;i++)
458 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
460 return r_farclip_meshfarclip - r_farclip_directiondist;
463 extern void R_Textures_Init(void);
464 extern void GL_Draw_Init(void);
465 extern void GL_Main_Init(void);
466 extern void R_Shadow_Init(void);
467 extern void R_Sky_Init(void);
468 extern void GL_Surf_Init(void);
469 extern void R_Crosshairs_Init(void);
470 extern void R_Light_Init(void);
471 extern void R_Particles_Init(void);
472 extern void R_Explosion_Init(void);
473 extern void gl_backend_init(void);
474 extern void Sbar_Init(void);
475 extern void R_LightningBeams_Init(void);
476 extern void Mod_RenderInit(void);
478 void Render_Init(void)
494 R_LightningBeams_Init();
503 extern char *ENGINE_EXTENSIONS;
506 VID_CheckExtensions();
508 // LordHavoc: report supported extensions
509 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
511 // clear to black (loading plaque will be seen over this)
512 qglClearColor(0,0,0,1);
513 qglClear(GL_COLOR_BUFFER_BIT);
516 int R_CullBox(const vec3_t mins, const vec3_t maxs)
520 for (i = 0;i < 4;i++)
527 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
531 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
535 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
539 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
543 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
547 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
551 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
555 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
563 //==================================================================================
565 static void R_MarkEntities (void)
568 entity_render_t *ent;
570 if (!r_drawentities.integer)
573 r_refdef.worldentity->visframe = r_framecount;
574 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
575 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
577 // worldmodel can check visibility
578 for (i = 0;i < r_refdef.numentities;i++)
580 ent = r_refdef.entities[i];
581 Mod_CheckLoaded(ent->model);
582 // some of the renderer still relies on origin...
583 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
584 // some of the renderer still relies on scale...
585 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
586 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_worldleafvisible, ent->mins, ent->maxs)))
588 R_UpdateEntLights(ent);
589 ent->visframe = r_framecount;
595 // no worldmodel or it can't check visibility
596 for (i = 0;i < r_refdef.numentities;i++)
598 ent = r_refdef.entities[i];
599 Mod_CheckLoaded(ent->model);
600 // some of the renderer still relies on origin...
601 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
602 // some of the renderer still relies on scale...
603 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
604 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
606 R_UpdateEntLights(ent);
607 ent->visframe = r_framecount;
613 // only used if skyrendermasked, and normally returns false
614 int R_DrawBrushModelsSky (void)
617 entity_render_t *ent;
619 if (!r_drawentities.integer)
623 for (i = 0;i < r_refdef.numentities;i++)
625 ent = r_refdef.entities[i];
626 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
628 ent->model->DrawSky(ent);
635 void R_DrawNoModel(entity_render_t *ent);
636 void R_DrawModels(void)
639 entity_render_t *ent;
641 if (!r_drawentities.integer)
644 for (i = 0;i < r_refdef.numentities;i++)
646 ent = r_refdef.entities[i];
647 if (ent->visframe == r_framecount)
649 if (ent->model && ent->model->Draw != NULL)
650 ent->model->Draw(ent);
657 static void R_SetFrustum(void)
659 // break apart the view matrix into vectors for various purposes
660 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
661 VectorNegate(r_viewleft, r_viewright);
663 // LordHavoc: note to all quake engine coders, the special case for 90
664 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
667 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
668 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
669 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
670 PlaneClassify(&frustum[0]);
672 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
673 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
674 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
675 PlaneClassify(&frustum[1]);
677 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
678 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
679 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
680 PlaneClassify(&frustum[2]);
682 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
683 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
684 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
685 PlaneClassify(&frustum[3]);
688 VectorCopy(r_viewforward, frustum[4].normal);
689 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
690 PlaneClassify(&frustum[4]);
693 static void R_BlendView(void)
697 if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
700 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
703 R_Mesh_Matrix(&r_identitymatrix);
704 // vertex coordinates for a quad that covers the screen exactly
705 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
706 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
707 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
708 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
709 if (r_bloom.integer && r_bloom_resolution.value >= 32 && r_bloom_power.integer >= 1 && r_bloom_power.integer < 100 && r_bloom_blur.value >= 0 && r_bloom_blur.value < 512)
711 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
712 float xoffset, yoffset, r;
714 // set the (poorly named) screenwidth and screenheight variables to
715 // a power of 2 at least as large as the screen, these will define the
716 // size of the texture to allocate
717 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
718 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
719 // allocate textures as needed
720 if (!r_bloom_texture_screen)
721 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
722 if (!r_bloom_texture_bloom)
723 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
724 // set bloomwidth and bloomheight to the bloom resolution that will be
725 // used (often less than the screen resolution for faster rendering)
726 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
727 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
728 // set up a texcoord array for the full resolution screen image
729 // (we have to keep this around to copy back during final render)
730 varray_texcoord2f[0][0] = 0;
731 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
732 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
733 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
734 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
735 varray_texcoord2f[0][5] = 0;
736 varray_texcoord2f[0][6] = 0;
737 varray_texcoord2f[0][7] = 0;
738 // set up a texcoord array for the reduced resolution bloom image
739 // (which will be additive blended over the screen image)
740 varray_texcoord2f[1][0] = 0;
741 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
742 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
743 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
744 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
745 varray_texcoord2f[1][5] = 0;
746 varray_texcoord2f[1][6] = 0;
747 varray_texcoord2f[1][7] = 0;
748 memset(&m, 0, sizeof(m));
749 m.pointer_vertex = varray_vertex3f;
750 m.pointer_texcoord[0] = varray_texcoord2f[0];
751 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
753 // copy view into the full resolution screen image texture
755 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
757 c_bloomcopypixels += r_view_width * r_view_height;
758 // now scale it down to the bloom size and raise to a power of itself
759 // to darken it (this leaves the really bright stuff bright, and
760 // everything else becomes very dark)
761 // TODO: optimize with multitexture or GLSL
762 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
763 GL_BlendFunc(GL_ONE, GL_ZERO);
764 GL_Color(1, 1, 1, 1);
765 R_Mesh_Draw(0, 4, 2, polygonelements);
767 c_bloomdrawpixels += bloomwidth * bloomheight;
768 // render multiple times with a multiply blendfunc to raise to a power
769 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
770 for (x = 1;x < r_bloom_power.integer;x++)
772 R_Mesh_Draw(0, 4, 2, polygonelements);
774 c_bloomdrawpixels += bloomwidth * bloomheight;
776 // we now have a darkened bloom image in the framebuffer, copy it into
777 // the bloom image texture for more processing
778 memset(&m, 0, sizeof(m));
779 m.pointer_vertex = varray_vertex3f;
780 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
781 m.pointer_texcoord[0] = varray_texcoord2f[2];
784 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
786 c_bloomcopypixels += bloomwidth * bloomheight;
787 // blend on at multiple vertical offsets to achieve a vertical blur
788 // TODO: do offset blends using GLSL
789 range = r_bloom_blur.integer * bloomwidth / 320;
790 GL_BlendFunc(GL_ONE, GL_ZERO);
791 for (x = -range;x <= range;x++)
793 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
794 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
795 // compute a texcoord array with the specified x and y offset
796 varray_texcoord2f[2][0] = xoffset+0;
797 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
798 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
799 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
800 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
801 varray_texcoord2f[2][5] = yoffset+0;
802 varray_texcoord2f[2][6] = xoffset+0;
803 varray_texcoord2f[2][7] = yoffset+0;
804 // this r value looks like a 'dot' particle, fading sharply to
805 // black at the edges
806 // (probably not realistic but looks good enough)
807 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
810 GL_Color(r, r, r, 1);
811 R_Mesh_Draw(0, 4, 2, polygonelements);
813 c_bloomdrawpixels += bloomwidth * bloomheight;
814 GL_BlendFunc(GL_ONE, GL_ONE);
816 // copy the vertically blurred bloom view to a texture
818 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
820 c_bloomcopypixels += bloomwidth * bloomheight;
821 // blend the vertically blurred image at multiple offsets horizontally
822 // to finish the blur effect
823 // TODO: do offset blends using GLSL
824 range = r_bloom_blur.integer * bloomwidth / 320;
825 GL_BlendFunc(GL_ONE, GL_ZERO);
826 for (x = -range;x <= range;x++)
828 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
829 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
830 // compute a texcoord array with the specified x and y offset
831 varray_texcoord2f[2][0] = xoffset+0;
832 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
833 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
834 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
835 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
836 varray_texcoord2f[2][5] = yoffset+0;
837 varray_texcoord2f[2][6] = xoffset+0;
838 varray_texcoord2f[2][7] = yoffset+0;
839 // this r value looks like a 'dot' particle, fading sharply to
840 // black at the edges
841 // (probably not realistic but looks good enough)
842 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
845 GL_Color(r, r, r, 1);
846 R_Mesh_Draw(0, 4, 2, polygonelements);
848 c_bloomdrawpixels += bloomwidth * bloomheight;
849 GL_BlendFunc(GL_ONE, GL_ONE);
851 // copy the blurred bloom view to a texture
853 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
855 c_bloomcopypixels += bloomwidth * bloomheight;
856 // go back to full view area
857 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
858 // put the original screen image back in place and blend the bloom
860 memset(&m, 0, sizeof(m));
861 m.pointer_vertex = varray_vertex3f;
862 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
863 m.pointer_texcoord[0] = varray_texcoord2f[0];
865 dobloomblend = false;
867 // do both in one pass if possible
868 if (r_textureunits.integer >= 2 && gl_combine.integer)
870 dobloomblend = false;
871 m.texcombinergb[1] = GL_ADD;
872 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
873 m.pointer_texcoord[1] = varray_texcoord2f[1];
879 GL_BlendFunc(GL_ONE, GL_ZERO);
881 R_Mesh_Draw(0, 4, 2, polygonelements);
883 c_bloomdrawpixels += r_view_width * r_view_height;
884 // now blend on the bloom texture if multipass
887 memset(&m, 0, sizeof(m));
888 m.pointer_vertex = varray_vertex3f;
889 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
890 m.pointer_texcoord[0] = varray_texcoord2f[1];
892 GL_BlendFunc(GL_ONE, GL_ONE);
894 R_Mesh_Draw(0, 4, 2, polygonelements);
896 c_bloomdrawpixels += r_view_width * r_view_height;
899 if (r_refdef.viewblend[3] >= 0.01f)
901 // apply a color tint to the whole view
902 memset(&m, 0, sizeof(m));
903 m.pointer_vertex = varray_vertex3f;
905 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
906 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
907 R_Mesh_Draw(0, 4, 2, polygonelements);
911 void R_RenderScene(void);
913 matrix4x4_t r_waterscrollmatrix;
920 void R_RenderView(void)
922 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
923 return; //Host_Error ("R_RenderView: NULL worldmodel");
925 r_view_width = bound(0, r_refdef.width, vid.width);
926 r_view_height = bound(0, r_refdef.height, vid.height);
928 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
929 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
931 r_view_fov_x = bound(1, r_refdef.fov_x, 170);
932 r_view_fov_y = bound(1, r_refdef.fov_y, 170);
933 r_view_matrix = r_refdef.viewentitymatrix;
934 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
935 r_rtworld = r_shadow_realtime_world.integer;
936 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
937 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
938 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
939 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
941 // GL is weird because it's bottom to top, r_view_y is top to bottom
942 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
943 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
944 GL_ScissorTest(true);
950 R_TimeReport("setup");
952 qglDepthFunc(GL_LEQUAL);
953 qglPolygonOffset(0, 0);
954 qglEnable(GL_POLYGON_OFFSET_FILL);
958 qglPolygonOffset(0, 0);
959 qglDisable(GL_POLYGON_OFFSET_FILL);
962 R_TimeReport("blendview");
964 GL_Scissor(0, 0, vid.width, vid.height);
965 GL_ScissorTest(false);
968 extern void R_DrawLightningBeams (void);
969 void R_RenderScene(void)
971 // don't let sound skip if going slow
972 if (r_refdef.extraupdate)
977 R_MeshQueue_BeginScene();
979 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
983 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
984 if (r_rtworldshadows || r_rtdlightshadows)
985 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
987 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
989 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
991 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);
996 R_TimeReport("worldvis");
999 R_TimeReport("markentity");
1001 R_Shadow_UpdateWorldLightSelection();
1003 // don't let sound skip if going slow
1004 if (r_refdef.extraupdate)
1007 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1008 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1010 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1011 R_TimeReport("worldsky");
1014 if (R_DrawBrushModelsSky())
1015 R_TimeReport("bmodelsky");
1017 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1018 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1020 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1021 R_TimeReport("world");
1024 // don't let sound skip if going slow
1025 if (r_refdef.extraupdate)
1028 GL_ShowTrisColor(0, 0.015, 0, 1);
1031 R_TimeReport("models");
1033 // don't let sound skip if going slow
1034 if (r_refdef.extraupdate)
1037 GL_ShowTrisColor(0, 0, 0.033, 1);
1038 R_ShadowVolumeLighting(false);
1039 R_TimeReport("rtlights");
1041 // don't let sound skip if going slow
1042 if (r_refdef.extraupdate)
1045 GL_ShowTrisColor(0.1, 0, 0, 1);
1047 R_DrawLightningBeams();
1048 R_TimeReport("lightning");
1051 R_TimeReport("particles");
1054 R_TimeReport("explosions");
1056 R_MeshQueue_RenderTransparent();
1057 R_TimeReport("drawtrans");
1060 R_TimeReport("coronas");
1062 R_DrawWorldCrosshair();
1063 R_TimeReport("crosshair");
1065 R_MeshQueue_Render();
1066 R_MeshQueue_EndScene();
1068 if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1070 R_ShadowVolumeLighting(true);
1071 R_TimeReport("visiblevolume");
1074 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1076 // don't let sound skip if going slow
1077 if (r_refdef.extraupdate)
1082 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1085 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1087 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1088 GL_DepthMask(false);
1090 R_Mesh_Matrix(&r_identitymatrix);
1092 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1093 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1094 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1095 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1096 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1097 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1098 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1099 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1100 R_FillColors(color, 8, cr, cg, cb, ca);
1103 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1105 VectorSubtract(v, r_vieworigin, diff);
1106 f2 = exp(fogdensity/DotProduct(diff, diff));
1108 c[0] = c[0] * f1 + fogcolor[0] * f2;
1109 c[1] = c[1] * f1 + fogcolor[1] * f2;
1110 c[2] = c[2] * f1 + fogcolor[2] * f2;
1113 memset(&m, 0, sizeof(m));
1114 m.pointer_vertex = vertex3f;
1115 m.pointer_color = color;
1121 int nomodelelements[24] =
1133 float nomodelvertex3f[6*3] =
1143 float nomodelcolor4f[6*4] =
1145 0.0f, 0.0f, 0.5f, 1.0f,
1146 0.0f, 0.0f, 0.5f, 1.0f,
1147 0.0f, 0.5f, 0.0f, 1.0f,
1148 0.0f, 0.5f, 0.0f, 1.0f,
1149 0.5f, 0.0f, 0.0f, 1.0f,
1150 0.5f, 0.0f, 0.0f, 1.0f
1153 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1155 const entity_render_t *ent = calldata1;
1157 float f1, f2, *c, diff[3];
1160 R_Mesh_Matrix(&ent->matrix);
1162 memset(&m, 0, sizeof(m));
1163 m.pointer_vertex = nomodelvertex3f;
1165 if (ent->flags & EF_ADDITIVE)
1167 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1168 GL_DepthMask(false);
1170 else if (ent->alpha < 1)
1172 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1173 GL_DepthMask(false);
1177 GL_BlendFunc(GL_ONE, GL_ZERO);
1180 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1183 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1184 m.pointer_color = color4f;
1185 VectorSubtract(ent->origin, r_vieworigin, diff);
1186 f2 = exp(fogdensity/DotProduct(diff, diff));
1188 for (i = 0, c = color4f;i < 6;i++, c += 4)
1190 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1191 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1192 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1196 else if (ent->alpha != 1)
1198 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1199 m.pointer_color = color4f;
1200 for (i = 0, c = color4f;i < 6;i++, c += 4)
1204 m.pointer_color = nomodelcolor4f;
1206 R_Mesh_Draw(0, 6, 8, nomodelelements);
1209 void R_DrawNoModel(entity_render_t *ent)
1211 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1212 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1214 // R_DrawNoModelCallback(ent, 0);
1217 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1219 vec3_t right1, right2, diff, normal;
1221 VectorSubtract (org2, org1, normal);
1223 // calculate 'right' vector for start
1224 VectorSubtract (r_vieworigin, org1, diff);
1225 CrossProduct (normal, diff, right1);
1226 VectorNormalize (right1);
1228 // calculate 'right' vector for end
1229 VectorSubtract (r_vieworigin, org2, diff);
1230 CrossProduct (normal, diff, right2);
1231 VectorNormalize (right2);
1233 vert[ 0] = org1[0] + width * right1[0];
1234 vert[ 1] = org1[1] + width * right1[1];
1235 vert[ 2] = org1[2] + width * right1[2];
1236 vert[ 3] = org1[0] - width * right1[0];
1237 vert[ 4] = org1[1] - width * right1[1];
1238 vert[ 5] = org1[2] - width * right1[2];
1239 vert[ 6] = org2[0] - width * right2[0];
1240 vert[ 7] = org2[1] - width * right2[1];
1241 vert[ 8] = org2[2] - width * right2[2];
1242 vert[ 9] = org2[0] + width * right2[0];
1243 vert[10] = org2[1] + width * right2[1];
1244 vert[11] = org2[2] + width * right2[2];
1247 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1249 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)
1256 VectorSubtract(origin, r_vieworigin, diff);
1257 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1260 R_Mesh_Matrix(&r_identitymatrix);
1261 GL_BlendFunc(blendfunc1, blendfunc2);
1262 GL_DepthMask(false);
1263 GL_DepthTest(!depthdisable);
1265 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1266 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1267 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1268 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1269 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1270 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1271 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1272 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1273 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1274 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1275 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1276 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1278 memset(&m, 0, sizeof(m));
1279 m.tex[0] = R_GetTexture(texture);
1280 m.pointer_texcoord[0] = spritetexcoord2f;
1281 m.pointer_vertex = varray_vertex3f;
1283 GL_Color(cr, cg, cb, ca);
1284 R_Mesh_Draw(0, 4, 2, polygonelements);
1287 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1291 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1292 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1294 if (i == mesh->numvertices)
1296 if (mesh->numvertices < mesh->maxvertices)
1298 VectorCopy(v, vertex3f);
1299 mesh->numvertices++;
1301 return mesh->numvertices;
1307 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1311 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1312 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1313 e = mesh->element3i + mesh->numtriangles * 3;
1314 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1316 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1317 if (mesh->numtriangles < mesh->maxtriangles)
1322 mesh->numtriangles++;
1324 element[1] = element[2];
1328 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1330 int planenum, planenum2;
1333 mplane_t *plane, *plane2;
1334 float temppoints[2][256*3];
1335 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1339 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1340 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1342 if (planenum2 == planenum)
1344 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);
1347 if (tempnumpoints < 3)
1349 // generate elements forming a triangle fan for this polygon
1350 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1354 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1356 texture_t *texture = t;
1357 model_t *model = ent->model;
1358 int s = ent->skinnum;
1359 if ((unsigned int)s >= (unsigned int)model->numskins)
1363 if (model->skinscenes)
1365 if (model->skinscenes[s].framecount > 1)
1366 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1368 s = model->skinscenes[s].firstframe;
1371 t = t + s * model->num_surfaces;
1373 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];
1374 texture->currentframe = t;
1375 t->currentmaterialflags = t->basematerialflags;
1376 t->currentalpha = ent->alpha;
1377 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1378 t->currentalpha *= r_wateralpha.value;
1379 if (!(ent->flags & RENDER_LIGHT))
1380 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1381 if (ent->effects & EF_ADDITIVE)
1382 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1383 else if (t->currentalpha < 1)
1384 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1385 if (ent->effects & EF_NODEPTHTEST)
1386 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1387 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1388 t->currenttexmatrix = r_waterscrollmatrix;
1390 t->currenttexmatrix = r_identitymatrix;
1393 void R_UpdateAllTextureInfo(entity_render_t *ent)
1397 for (i = 0;i < ent->model->num_textures;i++)
1398 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1401 float *rsurface_vertex3f;
1402 float *rsurface_svector3f;
1403 float *rsurface_tvector3f;
1404 float *rsurface_normal3f;
1405 float *rsurface_lightmapcolor4f;
1407 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1410 float center[3], forward[3], right[3], up[3], v[4][3];
1411 matrix4x4_t matrix1, imatrix1;
1412 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1414 rsurface_vertex3f = varray_vertex3f;
1415 rsurface_svector3f = NULL;
1416 rsurface_tvector3f = NULL;
1417 rsurface_normal3f = NULL;
1418 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1422 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1423 rsurface_svector3f = surface->groupmesh->data_svector3f;
1424 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1425 rsurface_normal3f = surface->groupmesh->data_normal3f;
1427 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1429 if (!rsurface_svector3f)
1431 rsurface_svector3f = varray_svector3f;
1432 rsurface_tvector3f = varray_tvector3f;
1433 rsurface_normal3f = varray_normal3f;
1434 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);
1436 // a single autosprite surface can contain multiple sprites...
1437 VectorClear(forward);
1439 VectorSet(up, 0, 0, 1);
1440 for (j = 0;j < surface->num_vertices - 3;j += 4)
1442 VectorClear(center);
1443 for (i = 0;i < 4;i++)
1444 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1445 VectorScale(center, 0.25f, center);
1446 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1447 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);
1448 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1449 for (i = 0;i < 4;i++)
1450 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1451 forward[0] = modelorg[0] - center[0];
1452 forward[1] = modelorg[1] - center[1];
1453 VectorNormalize(forward);
1454 right[0] = forward[1];
1455 right[1] = -forward[0];
1456 for (i = 0;i < 4;i++)
1457 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1459 rsurface_vertex3f = varray_vertex3f;
1460 rsurface_svector3f = NULL;
1461 rsurface_tvector3f = NULL;
1462 rsurface_normal3f = NULL;
1464 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1466 if (!rsurface_svector3f)
1468 rsurface_svector3f = varray_svector3f;
1469 rsurface_tvector3f = varray_tvector3f;
1470 rsurface_normal3f = varray_normal3f;
1471 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);
1473 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1474 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1475 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1476 // a single autosprite surface can contain multiple sprites...
1477 for (j = 0;j < surface->num_vertices - 3;j += 4)
1479 VectorClear(center);
1480 for (i = 0;i < 4;i++)
1481 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1482 VectorScale(center, 0.25f, center);
1483 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1484 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);
1485 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1486 for (i = 0;i < 4;i++)
1487 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1488 for (i = 0;i < 4;i++)
1489 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1491 rsurface_vertex3f = varray_vertex3f;
1492 rsurface_svector3f = NULL;
1493 rsurface_tvector3f = NULL;
1494 rsurface_normal3f = NULL;
1496 R_Mesh_VertexPointer(rsurface_vertex3f);
1499 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)
1507 vec4_t ambientcolor4f;
1508 vec3_t diffusecolor;
1509 vec3_t diffusenormal;
1510 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1512 rsurface_lightmapcolor4f = varray_color4f;
1513 if (rsurface_normal3f == NULL)
1515 rsurface_normal3f = varray_normal3f;
1516 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);
1518 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);
1527 r = ambientcolor4f[0];
1528 g = ambientcolor4f[1];
1529 b = ambientcolor4f[2];
1530 a = ambientcolor4f[3];
1531 rsurface_lightmapcolor4f = NULL;
1534 else if (lightmode >= 1)
1536 if (surface->lightmapinfo)
1538 rsurface_lightmapcolor4f = varray_color4f;
1539 for (i = 0, c = rsurface_lightmapcolor4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1541 const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1542 float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1543 VectorScale(lm, scale, c);
1544 if (surface->lightmapinfo->styles[1] != 255)
1546 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1548 scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1549 VectorMA(c, scale, lm, c);
1550 if (surface->lightmapinfo->styles[2] != 255)
1553 scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1554 VectorMA(c, scale, lm, c);
1555 if (surface->lightmapinfo->styles[3] != 255)
1558 scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1559 VectorMA(c, scale, lm, c);
1566 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1569 rsurface_lightmapcolor4f = NULL;
1572 if (rsurface_lightmapcolor4f)
1574 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)
1576 VectorSubtract(v, modelorg, diff);
1577 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1586 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)
1588 VectorSubtract(v, modelorg, diff);
1589 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1596 rsurface_lightmapcolor4f = varray_color4f;
1598 if (applycolor && rsurface_lightmapcolor4f)
1600 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)
1608 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1609 GL_Color(r, g, b, a);
1613 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1616 int texturesurfaceindex;
1620 float colorpants[3], colorshirt[3];
1621 float f, r, g, b, a, colorscale;
1622 const msurface_t *surface;
1623 qboolean dolightmap;
1627 qboolean fogallpasses;
1630 qboolean dofullbrightpants;
1631 qboolean dofullbrightshirt;
1632 qboolean applycolor;
1633 qboolean lightmode = 0;
1634 rtexture_t *basetexture;
1636 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1638 c_faces += texturenumsurfaces;
1639 // FIXME: identify models using a better check than ent->model->shadowmesh
1640 if (!(ent->effects & EF_FULLBRIGHT) && !ent->model->brush.shadowmesh)
1642 // gl_lightmaps debugging mode skips normal texturing
1643 if (gl_lightmaps.integer)
1645 GL_BlendFunc(GL_ONE, GL_ZERO);
1648 qglDisable(GL_CULL_FACE);
1649 GL_Color(1, 1, 1, 1);
1650 memset(&m, 0, sizeof(m));
1652 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1654 surface = texturesurfacelist[texturesurfaceindex];
1655 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1656 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1657 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1658 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, lightmode ? lightmode : !surface->lightmaptexture, false, false);
1659 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1660 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1661 GL_LockArrays(0, 0);
1663 qglEnable(GL_CULL_FACE);
1666 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1667 GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT));
1668 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
1669 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1670 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
1671 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1673 GL_BlendFunc(GL_ONE, GL_ZERO);
1674 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1675 qglDisable(GL_CULL_FACE);
1676 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
1680 skyrendernow = false;
1681 if (skyrendermasked)
1684 // LordHavoc: HalfLife maps have freaky skypolys...
1685 //if (!ent->model->brush.ishlbsp)
1687 R_Mesh_Matrix(&ent->matrix);
1688 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
1689 if (skyrendermasked)
1691 // depth-only (masking)
1692 GL_ColorMask(0,0,0,0);
1693 // just to make sure that braindead drivers don't draw anything
1694 // despite that colormask...
1695 GL_BlendFunc(GL_ZERO, GL_ONE);
1700 GL_BlendFunc(GL_ONE, GL_ZERO);
1704 memset(&m, 0, sizeof(m));
1706 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1708 surface = texturesurfacelist[texturesurfaceindex];
1709 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1710 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1711 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1712 GL_LockArrays(0, 0);
1714 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1717 else if (texture->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1719 // normal surface (wall or water)
1720 dolightmap = !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT);
1721 doambient = r_ambient.value >= (1/64.0f);
1722 doglow = texture->skin.glow != NULL;
1723 dofogpass = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD);
1724 fogallpasses = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
1725 if (ent->colormap >= 0)
1729 basetexture = texture->skin.base;
1730 dopants = texture->skin.pants != NULL;
1731 doshirt = texture->skin.shirt != NULL;
1732 // 128-224 are backwards ranges
1733 b = (ent->colormap & 0xF) << 4;b += (b >= 128 && b < 224) ? 4 : 12;
1734 dofullbrightpants = b >= 224;
1735 bcolor = (qbyte *) (&palette_complete[b]);
1736 VectorScale(bcolor, (1.0f / 255.0f), colorpants);
1737 // 128-224 are backwards ranges
1738 b = (ent->colormap & 0xF0);b += (b >= 128 && b < 224) ? 4 : 12;
1739 dofullbrightshirt = b >= 224;
1740 bcolor = (qbyte *) (&palette_complete[b]);
1741 VectorScale(bcolor, (1.0f / 255.0f), colorshirt);
1745 basetexture = texture->skin.merged ? texture->skin.merged : texture->skin.base;
1748 dofullbrightshirt = false;
1749 dofullbrightpants = false;
1751 if (dolightmap && r_textureunits.integer >= 2 && gl_combine.integer)
1753 memset(&m, 0, sizeof(m));
1754 m.tex[1] = R_GetTexture(basetexture);
1755 m.texmatrix[1] = texture->currenttexmatrix;
1756 m.texrgbscale[1] = 2;
1757 m.pointer_color = varray_color4f;
1759 // transparent is not affected by r_lightmapintensity
1760 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1761 colorscale = r_lightmapintensity;
1764 // q3bsp has no lightmap updates, so the lightstylevalue that
1765 // would normally be baked into the lightmaptexture must be
1766 // applied to the color
1767 if (ent->model->type == mod_brushq3)
1768 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
1769 r = ent->colormod[0] * colorscale;
1770 g = ent->colormod[1] * colorscale;
1771 b = ent->colormod[2] * colorscale;
1772 a = texture->currentalpha;
1773 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
1774 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1776 surface = texturesurfacelist[texturesurfaceindex];
1777 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1778 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1779 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1780 if (surface->lightmaptexture)
1781 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1783 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1784 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode ? lightmode : !surface->lightmaptexture, applycolor, fogallpasses);
1785 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1786 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1787 GL_LockArrays(0, 0);
1790 else if (dolightmap && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT) && !lightmode)
1793 GL_BlendFunc(GL_ONE, GL_ZERO);
1795 GL_Color(1, 1, 1, 1);
1796 memset(&m, 0, sizeof(m));
1798 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1800 surface = texturesurfacelist[texturesurfaceindex];
1801 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1802 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1803 if (surface->lightmaptexture)
1805 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1806 R_Mesh_ColorPointer(NULL);
1810 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1811 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
1813 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1814 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1815 GL_LockArrays(0, 0);
1817 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1818 GL_DepthMask(false);
1819 GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
1820 memset(&m, 0, sizeof(m));
1821 m.tex[0] = R_GetTexture(basetexture);
1822 m.texmatrix[0] = texture->currenttexmatrix;
1824 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1826 surface = texturesurfacelist[texturesurfaceindex];
1827 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1828 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1829 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1830 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1831 GL_LockArrays(0, 0);
1836 memset(&m, 0, sizeof(m));
1837 m.tex[0] = R_GetTexture(basetexture);
1838 m.texmatrix[0] = texture->currenttexmatrix;
1839 m.pointer_color = varray_color4f;
1841 if (gl_combine.integer)
1843 m.texrgbscale[0] = 2;
1846 // transparent is not affected by r_lightmapintensity
1847 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1848 colorscale *= r_lightmapintensity;
1849 // q3bsp has no lightmap updates, so the lightstylevalue that
1850 // would normally be baked into the lightmaptexture must be
1851 // applied to the color
1852 if (dolightmap && ent->model->type == mod_brushq3)
1853 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
1855 r = ent->colormod[0] * colorscale;
1856 g = ent->colormod[1] * colorscale;
1857 b = ent->colormod[2] * colorscale;
1858 a = texture->currentalpha;
1859 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
1862 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1864 surface = texturesurfacelist[texturesurfaceindex];
1865 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1866 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1867 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, fogallpasses);
1868 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1869 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1870 GL_LockArrays(0, 0);
1875 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1877 surface = texturesurfacelist[texturesurfaceindex];
1878 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1879 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1880 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
1881 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1882 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1883 GL_LockArrays(0, 0);
1889 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1890 memset(&m, 0, sizeof(m));
1891 m.tex[0] = R_GetTexture(texture->skin.pants);
1892 m.texmatrix[0] = texture->currenttexmatrix;
1893 m.pointer_color = varray_color4f;
1895 if (gl_combine.integer)
1897 m.texrgbscale[0] = 2;
1900 // transparent is not affected by r_lightmapintensity
1901 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1902 colorscale *= r_lightmapintensity;
1903 // q3bsp has no lightmap updates, so the lightstylevalue that
1904 // would normally be baked into the lightmaptexture must be
1905 // applied to the color
1906 if (dolightmap && !dofullbrightpants && ent->model->type == mod_brushq3)
1907 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
1909 r = ent->colormod[0] * colorpants[0] * colorscale;
1910 g = ent->colormod[1] * colorpants[1] * colorscale;
1911 b = ent->colormod[2] * colorpants[2] * colorscale;
1912 a = texture->currentalpha;
1913 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
1914 if (dolightmap && !dofullbrightpants)
1916 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1918 surface = texturesurfacelist[texturesurfaceindex];
1919 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1920 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1921 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, fogallpasses);
1922 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1923 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1924 GL_LockArrays(0, 0);
1929 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1931 surface = texturesurfacelist[texturesurfaceindex];
1932 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1933 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1934 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
1935 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1936 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1937 GL_LockArrays(0, 0);
1943 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1944 memset(&m, 0, sizeof(m));
1945 m.tex[0] = R_GetTexture(texture->skin.shirt);
1946 m.texmatrix[0] = texture->currenttexmatrix;
1947 m.pointer_color = varray_color4f;
1949 if (gl_combine.integer)
1951 m.texrgbscale[0] = 2;
1954 // transparent is not affected by r_lightmapintensity
1955 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1956 colorscale *= r_lightmapintensity;
1957 // q3bsp has no lightmap updates, so the lightstylevalue that
1958 // would normally be baked into the lightmaptexture must be
1959 // applied to the color
1960 if (dolightmap && !dofullbrightshirt && ent->model->type == mod_brushq3)
1961 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
1963 r = ent->colormod[0] * colorshirt[0] * colorscale;
1964 g = ent->colormod[1] * colorshirt[1] * colorscale;
1965 b = ent->colormod[2] * colorshirt[2] * colorscale;
1966 a = texture->currentalpha;
1967 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
1968 if (dolightmap && !dofullbrightshirt)
1970 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1972 surface = texturesurfacelist[texturesurfaceindex];
1973 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1974 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1975 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, fogallpasses);
1976 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1977 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1978 GL_LockArrays(0, 0);
1983 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1985 surface = texturesurfacelist[texturesurfaceindex];
1986 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1987 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1988 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
1989 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1990 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1991 GL_LockArrays(0, 0);
1998 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1999 GL_DepthMask(false);
2000 memset(&m, 0, sizeof(m));
2001 m.tex[0] = R_GetTexture(texture->skin.base);
2002 m.texmatrix[0] = texture->currenttexmatrix;
2003 m.pointer_color = varray_color4f;
2005 if (gl_combine.integer && (ent->colormod[0] > 1 || ent->colormod[1] > 1 || ent->colormod[2] > 1))
2007 m.texrgbscale[0] = 4;
2011 colorscale *= r_ambient.value * (1.0f / 64.0f);
2012 r = ent->colormod[0] * colorscale;
2013 g = ent->colormod[1] * colorscale;
2014 b = ent->colormod[2] * colorscale;
2015 a = texture->currentalpha;
2016 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2017 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2019 surface = texturesurfacelist[texturesurfaceindex];
2020 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2021 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2022 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2023 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2024 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2025 GL_LockArrays(0, 0);
2030 // if glow was not already done using multitexture, do it now.
2031 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2032 GL_DepthMask(false);
2033 memset(&m, 0, sizeof(m));
2034 m.tex[0] = R_GetTexture(texture->skin.glow);
2035 m.texmatrix[0] = texture->currenttexmatrix;
2036 m.pointer_color = varray_color4f;
2041 a = texture->currentalpha;
2042 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2043 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2045 surface = texturesurfacelist[texturesurfaceindex];
2046 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2047 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2048 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2049 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2050 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2051 GL_LockArrays(0, 0);
2056 // if this is opaque use alpha blend which will darken the earlier
2059 // if this is an alpha blended material, all the earlier passes
2060 // were darkened by fog already, so we only need to add the fog
2061 // color ontop through the fog mask texture
2063 // if this is an additive blended material, all the earlier passes
2064 // were darkened by fog already, and we should not add fog color
2065 // (because the background was not darkened, there is no fog color
2066 // that was lost behind it).
2068 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2070 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2071 GL_DepthMask(false);
2072 memset(&m, 0, sizeof(m));
2073 m.tex[0] = R_GetTexture(texture->skin.fog);
2074 m.texmatrix[0] = texture->currenttexmatrix;
2079 a = texture->currentalpha;
2080 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2081 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2083 surface = texturesurfacelist[texturesurfaceindex];
2084 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2085 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2086 R_Mesh_ColorPointer(varray_color4f);
2087 //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);
2088 if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2090 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)
2092 VectorSubtract(v, modelorg, diff);
2093 f = exp(fogdensity/DotProduct(diff, diff));
2097 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * f * a;
2102 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)
2104 VectorSubtract(v, modelorg, diff);
2105 f = exp(fogdensity/DotProduct(diff, diff));
2112 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2113 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2114 GL_LockArrays(0, 0);
2118 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2119 qglEnable(GL_CULL_FACE);
2122 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2124 const entity_render_t *ent = calldata1;
2125 const msurface_t *surface = ent->model->data_surfaces + calldata2;
2129 texture = surface->texture;
2130 if (texture->basematerialflags & MATERIALFLAG_SKY)
2131 return; // transparent sky is too difficult
2132 R_UpdateTextureInfo(ent, texture);
2134 R_Mesh_Matrix(&ent->matrix);
2135 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2136 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2139 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2141 int texturesurfaceindex;
2142 const msurface_t *surface;
2143 vec3_t tempcenter, center;
2144 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2146 // drawing sky transparently would be too difficult
2147 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2149 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2151 surface = texturesurfacelist[texturesurfaceindex];
2152 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2153 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2154 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2155 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2156 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2161 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2164 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2165 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2167 int i, j, f, flagsmask;
2168 msurface_t *surface, **surfacechain;
2169 texture_t *t, *texture;
2170 model_t *model = ent->model;
2172 const int maxsurfacelist = 1024;
2173 int numsurfacelist = 0;
2174 const msurface_t *surfacelist[1024];
2177 R_Mesh_Matrix(&ent->matrix);
2178 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2180 // update light styles
2181 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2183 for (i = 0;i < model->brushq1.light_styles;i++)
2185 if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
2187 model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
2188 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2189 for (;(surface = *surfacechain);surfacechain++)
2190 surface->cached_dlight = true;
2195 R_UpdateAllTextureInfo(ent);
2196 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2201 if (ent == r_refdef.worldentity)
2203 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2205 if (!r_worldsurfacevisible[j])
2207 if (t != surface->texture)
2211 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2214 t = surface->texture;
2215 texture = t->currentframe;
2216 f = texture->currentmaterialflags & flagsmask;
2218 if (f && surface->num_triangles)
2220 // if lightmap parameters changed, rebuild lightmap texture
2221 if (surface->cached_dlight && surface->lightmapinfo->samples)
2222 R_BuildLightMap(ent, surface);
2223 // add face to draw list
2224 surfacelist[numsurfacelist++] = surface;
2225 if (numsurfacelist >= maxsurfacelist)
2227 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2235 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2237 if (t != surface->texture)
2241 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2244 t = surface->texture;
2245 texture = t->currentframe;
2246 f = texture->currentmaterialflags & flagsmask;
2248 if (f && surface->num_triangles)
2250 // if lightmap parameters changed, rebuild lightmap texture
2251 if (surface->cached_dlight && surface->lightmapinfo->samples)
2252 R_BuildLightMap(ent, surface);
2253 // add face to draw list
2254 surfacelist[numsurfacelist++] = surface;
2255 if (numsurfacelist >= maxsurfacelist)
2257 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2264 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);