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 renderstats_t renderstats;
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 cvar_t r_showtris = {0, "r_showtris", "0"};
75 cvar_t r_drawentities = {0, "r_drawentities","1"};
76 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
77 cvar_t r_speeds = {0, "r_speeds","0"};
78 cvar_t r_fullbright = {0, "r_fullbright","0"};
79 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
80 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
81 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
82 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
84 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
85 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
86 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
87 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
88 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
89 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
90 cvar_t gl_fogend = {0, "gl_fogend","0"};
92 cvar_t r_textureunits = {0, "r_textureunits", "32"};
94 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
95 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
96 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
98 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0"};
99 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "2"};
100 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "8"};
101 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
102 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"};
104 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1"};
106 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0"};
108 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
110 cvar_t r_test = {0, "r_test", "0"}; // used for testing renderer code changes, otherwise does nothing
112 rtexturepool_t *r_main_texturepool;
113 rtexture_t *r_bloom_texture_screen;
114 rtexture_t *r_bloom_texture_bloom;
115 rtexture_t *r_texture_blanknormalmap;
116 rtexture_t *r_texture_white;
117 rtexture_t *r_texture_black;
118 rtexture_t *r_texture_notexture;
119 rtexture_t *r_texture_whitecube;
120 rtexture_t *r_texture_normalizationcube;
121 rtexture_t *r_texture_fogattenuation;
122 rtexture_t *r_texture_fogintensity;
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++)
156 vec_t fogtabledistmultiplier;
157 float fogtable[FOGTABLEWIDTH];
158 float fog_density, fog_red, fog_green, fog_blue;
160 qboolean oldgl_fogenable;
161 void R_UpdateFog(void)
163 if (gamemode == GAME_NEHAHRA)
165 if (gl_fogenable.integer)
167 oldgl_fogenable = true;
168 fog_density = gl_fogdensity.value;
169 fog_red = gl_fogred.value;
170 fog_green = gl_foggreen.value;
171 fog_blue = gl_fogblue.value;
173 else if (oldgl_fogenable)
175 oldgl_fogenable = false;
184 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
185 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
186 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
191 fogdensity = -4000.0f / (fog_density * fog_density);
192 // this is the point where the fog reaches 0.9986 alpha, which we
193 // consider a good enough cutoff point for the texture
194 // (0.9986 * 256 == 255.6)
195 fogrange = 400 / fog_density;
196 fograngerecip = 1.0f / fogrange;
197 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
198 // fog color was already set
204 // FIXME: move this to client?
207 if (gamemode == GAME_NEHAHRA)
209 Cvar_Set("gl_fogenable", "0");
210 Cvar_Set("gl_fogdensity", "0.2");
211 Cvar_Set("gl_fogred", "0.3");
212 Cvar_Set("gl_foggreen", "0.3");
213 Cvar_Set("gl_fogblue", "0.3");
215 fog_density = fog_red = fog_green = fog_blue = 0.0f;
218 // FIXME: move this to client?
219 void FOG_registercvars(void)
224 if (gamemode == GAME_NEHAHRA)
226 Cvar_RegisterVariable (&gl_fogenable);
227 Cvar_RegisterVariable (&gl_fogdensity);
228 Cvar_RegisterVariable (&gl_fogred);
229 Cvar_RegisterVariable (&gl_foggreen);
230 Cvar_RegisterVariable (&gl_fogblue);
231 Cvar_RegisterVariable (&gl_fogstart);
232 Cvar_RegisterVariable (&gl_fogend);
235 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
236 for (x = 0;x < FOGTABLEWIDTH;x++)
238 alpha = exp(r / ((double)x*(double)x));
239 if (x == FOGTABLEWIDTH - 1)
241 fogtable[x] = bound(0, alpha, 1);
245 static void R_BuildBlankTextures(void)
247 unsigned char data[4];
248 data[0] = 128; // normal X
249 data[1] = 128; // normal Y
250 data[2] = 255; // normal Z
251 data[3] = 128; // height
252 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
257 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
262 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
265 static void R_BuildNoTexture(void)
268 unsigned char pix[16][16][4];
269 // this makes a light grey/dark grey checkerboard texture
270 for (y = 0;y < 16;y++)
272 for (x = 0;x < 16;x++)
274 if ((y < 8) ^ (x < 8))
290 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
293 static void R_BuildWhiteCube(void)
295 unsigned char data[6*1*1*4];
296 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
297 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
298 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
299 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
300 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
301 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
302 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
305 static void R_BuildNormalizationCube(void)
309 vec_t s, t, intensity;
311 unsigned char data[6][NORMSIZE][NORMSIZE][4];
312 for (side = 0;side < 6;side++)
314 for (y = 0;y < NORMSIZE;y++)
316 for (x = 0;x < NORMSIZE;x++)
318 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
319 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
354 intensity = 127.0f / sqrt(DotProduct(v, v));
355 data[side][y][x][0] = 128.0f + intensity * v[0];
356 data[side][y][x][1] = 128.0f + intensity * v[1];
357 data[side][y][x][2] = 128.0f + intensity * v[2];
358 data[side][y][x][3] = 255;
362 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
365 static void R_BuildFogTexture(void)
370 unsigned char data1[FOGWIDTH][4];
371 unsigned char data2[FOGWIDTH][4];
372 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
373 for (x = 0;x < FOGWIDTH;x++)
375 alpha = exp(r / ((double)x*(double)x));
376 if (x == FOGWIDTH - 1)
378 b = (int)(256.0 * alpha);
379 b = bound(0, b, 255);
380 data1[x][0] = 255 - b;
381 data1[x][1] = 255 - b;
382 data1[x][2] = 255 - b;
389 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
390 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
393 void gl_main_start(void)
395 r_main_texturepool = R_AllocTexturePool();
396 r_bloom_texture_screen = NULL;
397 r_bloom_texture_bloom = NULL;
398 R_BuildBlankTextures();
400 if (gl_texturecubemap)
403 R_BuildNormalizationCube();
408 void gl_main_shutdown(void)
410 R_FreeTexturePool(&r_main_texturepool);
411 r_bloom_texture_screen = NULL;
412 r_bloom_texture_bloom = NULL;
413 r_texture_blanknormalmap = NULL;
414 r_texture_white = NULL;
415 r_texture_black = NULL;
416 r_texture_whitecube = NULL;
417 r_texture_normalizationcube = NULL;
420 extern void CL_ParseEntityLump(char *entitystring);
421 void gl_main_newmap(void)
423 // FIXME: move this code to client
425 char *entities, entname[MAX_QPATH];
429 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
430 l = (int)strlen(entname) - 4;
431 if (l >= 0 && !strcmp(entname + l, ".bsp"))
433 strcpy(entname + l, ".ent");
434 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
436 CL_ParseEntityLump(entities);
441 if (cl.worldmodel->brush.entities)
442 CL_ParseEntityLump(cl.worldmodel->brush.entities);
446 void GL_Main_Init(void)
448 Matrix4x4_CreateIdentity(&r_identitymatrix);
449 // FIXME: move this to client?
451 Cvar_RegisterVariable(&r_showtris);
452 Cvar_RegisterVariable(&r_drawentities);
453 Cvar_RegisterVariable(&r_drawviewmodel);
454 Cvar_RegisterVariable(&r_speeds);
455 Cvar_RegisterVariable(&r_fullbrights);
456 Cvar_RegisterVariable(&r_wateralpha);
457 Cvar_RegisterVariable(&r_dynamic);
458 Cvar_RegisterVariable(&r_fullbright);
459 Cvar_RegisterVariable(&r_textureunits);
460 Cvar_RegisterVariable(&r_lerpsprites);
461 Cvar_RegisterVariable(&r_lerpmodels);
462 Cvar_RegisterVariable(&r_waterscroll);
463 Cvar_RegisterVariable(&r_drawcollisionbrushes);
464 Cvar_RegisterVariable(&r_bloom);
465 Cvar_RegisterVariable(&r_bloom_intensity);
466 Cvar_RegisterVariable(&r_bloom_blur);
467 Cvar_RegisterVariable(&r_bloom_resolution);
468 Cvar_RegisterVariable(&r_bloom_power);
469 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
470 Cvar_RegisterVariable(&developer_texturelogging);
471 Cvar_RegisterVariable(&gl_lightmaps);
472 Cvar_RegisterVariable(&r_test);
473 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
474 Cvar_SetValue("r_fullbrights", 0);
475 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
478 static vec3_t r_farclip_origin;
479 static vec3_t r_farclip_direction;
480 static vec_t r_farclip_directiondist;
481 static vec_t r_farclip_meshfarclip;
482 static int r_farclip_directionbit0;
483 static int r_farclip_directionbit1;
484 static int r_farclip_directionbit2;
486 // enlarge farclip to accomodate box
487 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
490 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
491 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
492 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
493 if (r_farclip_meshfarclip < d)
494 r_farclip_meshfarclip = d;
497 // return farclip value
498 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
502 VectorCopy(origin, r_farclip_origin);
503 VectorCopy(direction, r_farclip_direction);
504 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
505 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
506 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
507 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
508 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
510 if (r_refdef.worldmodel)
511 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
512 for (i = 0;i < r_refdef.numentities;i++)
513 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
515 return r_farclip_meshfarclip - r_farclip_directiondist;
518 extern void R_Textures_Init(void);
519 extern void GL_Draw_Init(void);
520 extern void GL_Main_Init(void);
521 extern void R_Shadow_Init(void);
522 extern void R_Sky_Init(void);
523 extern void GL_Surf_Init(void);
524 extern void R_Crosshairs_Init(void);
525 extern void R_Light_Init(void);
526 extern void R_Particles_Init(void);
527 extern void R_Explosion_Init(void);
528 extern void gl_backend_init(void);
529 extern void Sbar_Init(void);
530 extern void R_LightningBeams_Init(void);
531 extern void Mod_RenderInit(void);
533 void Render_Init(void)
549 R_LightningBeams_Init();
558 extern char *ENGINE_EXTENSIONS;
561 VID_CheckExtensions();
563 // LordHavoc: report supported extensions
564 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
566 // clear to black (loading plaque will be seen over this)
567 qglClearColor(0,0,0,1);
568 qglClear(GL_COLOR_BUFFER_BIT);
571 int R_CullBox(const vec3_t mins, const vec3_t maxs)
575 for (i = 0;i < 4;i++)
582 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
586 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
590 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
594 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
598 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
602 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
606 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
610 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
618 //==================================================================================
620 static void R_MarkEntities (void)
623 entity_render_t *ent;
625 if (!r_drawentities.integer)
628 r_refdef.worldentity->visframe = r_framecount;
629 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
630 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
632 // worldmodel can check visibility
633 for (i = 0;i < r_refdef.numentities;i++)
635 ent = r_refdef.entities[i];
636 // some of the renderer still relies on origin...
637 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
638 // some of the renderer still relies on scale...
639 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
640 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)))
642 R_UpdateEntLights(ent);
643 ent->visframe = r_framecount;
649 // no worldmodel or it can't check visibility
650 for (i = 0;i < r_refdef.numentities;i++)
652 ent = r_refdef.entities[i];
653 // some of the renderer still relies on origin...
654 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
655 // some of the renderer still relies on scale...
656 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
657 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
659 R_UpdateEntLights(ent);
660 ent->visframe = r_framecount;
666 // only used if skyrendermasked, and normally returns false
667 int R_DrawBrushModelsSky (void)
670 entity_render_t *ent;
672 if (!r_drawentities.integer)
676 for (i = 0;i < r_refdef.numentities;i++)
678 ent = r_refdef.entities[i];
679 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
681 ent->model->DrawSky(ent);
688 void R_DrawNoModel(entity_render_t *ent);
689 void R_DrawModels(void)
692 entity_render_t *ent;
694 if (!r_drawentities.integer)
697 for (i = 0;i < r_refdef.numentities;i++)
699 ent = r_refdef.entities[i];
700 if (ent->visframe == r_framecount)
702 renderstats.entities++;
703 if (ent->model && ent->model->Draw != NULL)
704 ent->model->Draw(ent);
711 static void R_SetFrustum(void)
713 // break apart the view matrix into vectors for various purposes
714 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
715 VectorNegate(r_viewleft, r_viewright);
717 // LordHavoc: note to all quake engine coders, the special case for 90
718 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
721 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
722 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
723 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
724 PlaneClassify(&frustum[0]);
726 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
727 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
728 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
729 PlaneClassify(&frustum[1]);
731 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
732 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
733 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
734 PlaneClassify(&frustum[2]);
736 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
737 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
738 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
739 PlaneClassify(&frustum[3]);
742 VectorCopy(r_viewforward, frustum[4].normal);
743 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
744 PlaneClassify(&frustum[4]);
747 static void R_BlendView(void)
751 if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
754 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
757 R_Mesh_Matrix(&r_identitymatrix);
758 // vertex coordinates for a quad that covers the screen exactly
759 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
760 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
761 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
762 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
763 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)
765 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
766 float xoffset, yoffset, r;
768 // set the (poorly named) screenwidth and screenheight variables to
769 // a power of 2 at least as large as the screen, these will define the
770 // size of the texture to allocate
771 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
772 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
773 // allocate textures as needed
774 if (!r_bloom_texture_screen)
775 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
776 if (!r_bloom_texture_bloom)
777 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
778 // set bloomwidth and bloomheight to the bloom resolution that will be
779 // used (often less than the screen resolution for faster rendering)
780 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
781 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
782 // set up a texcoord array for the full resolution screen image
783 // (we have to keep this around to copy back during final render)
784 varray_texcoord2f[0][0] = 0;
785 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
786 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
787 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
788 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
789 varray_texcoord2f[0][5] = 0;
790 varray_texcoord2f[0][6] = 0;
791 varray_texcoord2f[0][7] = 0;
792 // set up a texcoord array for the reduced resolution bloom image
793 // (which will be additive blended over the screen image)
794 varray_texcoord2f[1][0] = 0;
795 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
796 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
797 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
798 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
799 varray_texcoord2f[1][5] = 0;
800 varray_texcoord2f[1][6] = 0;
801 varray_texcoord2f[1][7] = 0;
802 memset(&m, 0, sizeof(m));
803 m.pointer_vertex = varray_vertex3f;
804 m.pointer_texcoord[0] = varray_texcoord2f[0];
805 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
807 // copy view into the full resolution screen image texture
809 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
810 renderstats.bloom_copypixels += r_view_width * r_view_height;
811 // now scale it down to the bloom size and raise to a power of itself
812 // to darken it (this leaves the really bright stuff bright, and
813 // everything else becomes very dark)
814 // TODO: optimize with multitexture or GLSL
815 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
816 GL_BlendFunc(GL_ONE, GL_ZERO);
817 GL_Color(1, 1, 1, 1);
818 R_Mesh_Draw(0, 4, 2, polygonelements);
819 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
820 // render multiple times with a multiply blendfunc to raise to a power
821 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
822 for (x = 1;x < r_bloom_power.integer;x++)
824 R_Mesh_Draw(0, 4, 2, polygonelements);
825 renderstats.bloom_drawpixels += 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);
836 renderstats.bloom_copypixels += bloomwidth * bloomheight;
837 // blend on at multiple vertical offsets to achieve a vertical blur
838 // TODO: do offset blends using GLSL
839 range = r_bloom_blur.integer * bloomwidth / 320;
840 GL_BlendFunc(GL_ONE, GL_ZERO);
841 for (x = -range;x <= range;x++)
843 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
844 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
845 // compute a texcoord array with the specified x and y offset
846 varray_texcoord2f[2][0] = xoffset+0;
847 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
848 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
849 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
850 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
851 varray_texcoord2f[2][5] = yoffset+0;
852 varray_texcoord2f[2][6] = xoffset+0;
853 varray_texcoord2f[2][7] = yoffset+0;
854 // this r value looks like a 'dot' particle, fading sharply to
855 // black at the edges
856 // (probably not realistic but looks good enough)
857 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
860 GL_Color(r, r, r, 1);
861 R_Mesh_Draw(0, 4, 2, polygonelements);
862 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
863 GL_BlendFunc(GL_ONE, GL_ONE);
865 // copy the vertically blurred bloom view to a texture
867 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
868 renderstats.bloom_copypixels += bloomwidth * bloomheight;
869 // blend the vertically blurred image at multiple offsets horizontally
870 // to finish the blur effect
871 // TODO: do offset blends using GLSL
872 range = r_bloom_blur.integer * bloomwidth / 320;
873 GL_BlendFunc(GL_ONE, GL_ZERO);
874 for (x = -range;x <= range;x++)
876 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
877 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
878 // compute a texcoord array with the specified x and y offset
879 varray_texcoord2f[2][0] = xoffset+0;
880 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
881 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
882 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
883 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
884 varray_texcoord2f[2][5] = yoffset+0;
885 varray_texcoord2f[2][6] = xoffset+0;
886 varray_texcoord2f[2][7] = yoffset+0;
887 // this r value looks like a 'dot' particle, fading sharply to
888 // black at the edges
889 // (probably not realistic but looks good enough)
890 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
893 GL_Color(r, r, r, 1);
894 R_Mesh_Draw(0, 4, 2, polygonelements);
895 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
896 GL_BlendFunc(GL_ONE, GL_ONE);
898 // copy the blurred bloom view to a texture
900 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
901 renderstats.bloom_copypixels += bloomwidth * bloomheight;
902 // go back to full view area
903 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
904 // put the original screen image back in place and blend the bloom
906 memset(&m, 0, sizeof(m));
907 m.pointer_vertex = varray_vertex3f;
908 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
909 m.pointer_texcoord[0] = varray_texcoord2f[0];
911 dobloomblend = false;
913 // do both in one pass if possible
914 if (r_textureunits.integer >= 2 && gl_combine.integer)
916 dobloomblend = false;
917 m.texcombinergb[1] = GL_ADD;
918 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
919 m.pointer_texcoord[1] = varray_texcoord2f[1];
925 GL_BlendFunc(GL_ONE, GL_ZERO);
927 R_Mesh_Draw(0, 4, 2, polygonelements);
928 renderstats.bloom_drawpixels += r_view_width * r_view_height;
929 // now blend on the bloom texture if multipass
932 memset(&m, 0, sizeof(m));
933 m.pointer_vertex = varray_vertex3f;
934 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
935 m.pointer_texcoord[0] = varray_texcoord2f[1];
937 GL_BlendFunc(GL_ONE, GL_ONE);
939 R_Mesh_Draw(0, 4, 2, polygonelements);
940 renderstats.bloom_drawpixels += r_view_width * r_view_height;
943 if (r_refdef.viewblend[3] >= 0.01f)
945 // apply a color tint to the whole view
946 memset(&m, 0, sizeof(m));
947 m.pointer_vertex = varray_vertex3f;
949 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
950 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
951 R_Mesh_Draw(0, 4, 2, polygonelements);
955 void R_RenderScene(void);
957 matrix4x4_t r_waterscrollmatrix;
964 void R_RenderView(void)
966 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
967 return; //Host_Error ("R_RenderView: NULL worldmodel");
969 r_view_width = bound(0, r_refdef.width, vid.width);
970 r_view_height = bound(0, r_refdef.height, vid.height);
972 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
973 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
975 r_view_fov_x = bound(1, r_refdef.fov_x, 170);
976 r_view_fov_y = bound(1, r_refdef.fov_y, 170);
977 r_view_matrix = r_refdef.viewentitymatrix;
978 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
979 r_rtworld = r_shadow_realtime_world.integer;
980 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
981 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
982 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
983 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
985 // GL is weird because it's bottom to top, r_view_y is top to bottom
986 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
987 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
988 GL_ScissorTest(true);
993 R_TimeReport("setup");
995 qglDepthFunc(GL_LEQUAL);
996 qglPolygonOffset(0, 0);
997 qglEnable(GL_POLYGON_OFFSET_FILL);
1001 qglPolygonOffset(0, 0);
1002 qglDisable(GL_POLYGON_OFFSET_FILL);
1005 R_TimeReport("blendview");
1007 GL_Scissor(0, 0, vid.width, vid.height);
1008 GL_ScissorTest(false);
1011 extern void R_DrawLightningBeams (void);
1012 void R_RenderScene(void)
1014 // don't let sound skip if going slow
1015 if (r_refdef.extraupdate)
1020 R_MeshQueue_BeginScene();
1022 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1026 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1027 if (r_rtworldshadows || r_rtdlightshadows)
1028 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
1030 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
1032 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1034 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);
1038 R_WorldVisibility();
1039 R_TimeReport("worldvis");
1042 R_TimeReport("markentity");
1044 R_Shadow_UpdateWorldLightSelection();
1046 // don't let sound skip if going slow
1047 if (r_refdef.extraupdate)
1050 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1051 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1053 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1054 R_TimeReport("worldsky");
1057 if (R_DrawBrushModelsSky())
1058 R_TimeReport("bmodelsky");
1060 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1061 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1063 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1064 R_TimeReport("world");
1067 // don't let sound skip if going slow
1068 if (r_refdef.extraupdate)
1071 GL_ShowTrisColor(0, 0.015, 0, 1);
1074 R_TimeReport("models");
1076 // don't let sound skip if going slow
1077 if (r_refdef.extraupdate)
1080 GL_ShowTrisColor(0, 0, 0.033, 1);
1081 R_ShadowVolumeLighting(false);
1082 R_TimeReport("rtlights");
1084 // don't let sound skip if going slow
1085 if (r_refdef.extraupdate)
1088 GL_ShowTrisColor(0.1, 0, 0, 1);
1090 R_DrawLightningBeams();
1091 R_TimeReport("lightning");
1094 R_TimeReport("particles");
1097 R_TimeReport("explosions");
1099 R_MeshQueue_RenderTransparent();
1100 R_TimeReport("drawtrans");
1103 R_TimeReport("coronas");
1105 R_DrawWorldCrosshair();
1106 R_TimeReport("crosshair");
1108 R_MeshQueue_Render();
1109 R_MeshQueue_EndScene();
1111 if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1113 R_ShadowVolumeLighting(true);
1114 R_TimeReport("visiblevolume");
1117 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1119 // don't let sound skip if going slow
1120 if (r_refdef.extraupdate)
1125 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1128 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1130 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1131 GL_DepthMask(false);
1133 R_Mesh_Matrix(&r_identitymatrix);
1135 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1136 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1137 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1138 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1139 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1140 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1141 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1142 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1143 R_FillColors(color, 8, cr, cg, cb, ca);
1146 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1148 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1150 c[0] = c[0] * f1 + fogcolor[0] * f2;
1151 c[1] = c[1] * f1 + fogcolor[1] * f2;
1152 c[2] = c[2] * f1 + fogcolor[2] * f2;
1155 memset(&m, 0, sizeof(m));
1156 m.pointer_vertex = vertex3f;
1157 m.pointer_color = color;
1163 int nomodelelements[24] =
1175 float nomodelvertex3f[6*3] =
1185 float nomodelcolor4f[6*4] =
1187 0.0f, 0.0f, 0.5f, 1.0f,
1188 0.0f, 0.0f, 0.5f, 1.0f,
1189 0.0f, 0.5f, 0.0f, 1.0f,
1190 0.0f, 0.5f, 0.0f, 1.0f,
1191 0.5f, 0.0f, 0.0f, 1.0f,
1192 0.5f, 0.0f, 0.0f, 1.0f
1195 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1197 const entity_render_t *ent = (entity_render_t *)calldata1;
1202 R_Mesh_Matrix(&ent->matrix);
1204 memset(&m, 0, sizeof(m));
1205 m.pointer_vertex = nomodelvertex3f;
1207 if (ent->flags & EF_ADDITIVE)
1209 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1210 GL_DepthMask(false);
1212 else if (ent->alpha < 1)
1214 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1215 GL_DepthMask(false);
1219 GL_BlendFunc(GL_ONE, GL_ZERO);
1222 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1225 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1226 m.pointer_color = color4f;
1227 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1229 for (i = 0, c = color4f;i < 6;i++, c += 4)
1231 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1232 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1233 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1237 else if (ent->alpha != 1)
1239 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1240 m.pointer_color = color4f;
1241 for (i = 0, c = color4f;i < 6;i++, c += 4)
1245 m.pointer_color = nomodelcolor4f;
1247 R_Mesh_Draw(0, 6, 8, nomodelelements);
1250 void R_DrawNoModel(entity_render_t *ent)
1252 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1253 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1255 // R_DrawNoModelCallback(ent, 0);
1258 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1260 vec3_t right1, right2, diff, normal;
1262 VectorSubtract (org2, org1, normal);
1264 // calculate 'right' vector for start
1265 VectorSubtract (r_vieworigin, org1, diff);
1266 CrossProduct (normal, diff, right1);
1267 VectorNormalize (right1);
1269 // calculate 'right' vector for end
1270 VectorSubtract (r_vieworigin, org2, diff);
1271 CrossProduct (normal, diff, right2);
1272 VectorNormalize (right2);
1274 vert[ 0] = org1[0] + width * right1[0];
1275 vert[ 1] = org1[1] + width * right1[1];
1276 vert[ 2] = org1[2] + width * right1[2];
1277 vert[ 3] = org1[0] - width * right1[0];
1278 vert[ 4] = org1[1] - width * right1[1];
1279 vert[ 5] = org1[2] - width * right1[2];
1280 vert[ 6] = org2[0] - width * right2[0];
1281 vert[ 7] = org2[1] - width * right2[1];
1282 vert[ 8] = org2[2] - width * right2[2];
1283 vert[ 9] = org2[0] + width * right2[0];
1284 vert[10] = org2[1] + width * right2[1];
1285 vert[11] = org2[2] + width * right2[2];
1288 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1290 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, 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)
1292 float fog = 0.0f, ifog;
1296 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1299 R_Mesh_Matrix(&r_identitymatrix);
1300 GL_BlendFunc(blendfunc1, blendfunc2);
1301 GL_DepthMask(false);
1302 GL_DepthTest(!depthdisable);
1304 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1305 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1306 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1307 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1308 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1309 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1310 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1311 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1312 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1313 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1314 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1315 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1317 memset(&m, 0, sizeof(m));
1318 m.tex[0] = R_GetTexture(texture);
1319 m.pointer_texcoord[0] = spritetexcoord2f;
1320 m.pointer_vertex = varray_vertex3f;
1322 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
1323 R_Mesh_Draw(0, 4, 2, polygonelements);
1325 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
1327 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
1328 GL_BlendFunc(blendfunc1, GL_ONE);
1329 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
1330 R_Mesh_Draw(0, 4, 2, polygonelements);
1334 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1338 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1339 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1341 if (i == mesh->numvertices)
1343 if (mesh->numvertices < mesh->maxvertices)
1345 VectorCopy(v, vertex3f);
1346 mesh->numvertices++;
1348 return mesh->numvertices;
1354 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1358 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1359 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1360 e = mesh->element3i + mesh->numtriangles * 3;
1361 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1363 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1364 if (mesh->numtriangles < mesh->maxtriangles)
1369 mesh->numtriangles++;
1371 element[1] = element[2];
1375 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1377 int planenum, planenum2;
1380 mplane_t *plane, *plane2;
1381 float temppoints[2][256*3];
1382 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1386 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1387 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1389 if (planenum2 == planenum)
1391 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);
1394 if (tempnumpoints < 3)
1396 // generate elements forming a triangle fan for this polygon
1397 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1401 void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, matrix4x4_t *matrix, float r, float g, float b, float a)
1403 texturelayer_t *layer;
1404 layer = t->currentlayers + t->currentnumlayers++;
1406 layer->depthmask = depthmask;
1407 layer->blendfunc1 = blendfunc1;
1408 layer->blendfunc2 = blendfunc2;
1409 layer->texture = texture;
1410 layer->texmatrix = *matrix;
1411 layer->color[0] = r;
1412 layer->color[1] = g;
1413 layer->color[2] = b;
1414 layer->color[3] = a;
1417 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1419 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1420 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1424 texture_t *texture = t;
1425 model_t *model = ent->model;
1426 int s = ent->skinnum;
1427 if ((unsigned int)s >= (unsigned int)model->numskins)
1429 if (model->skinscenes)
1431 if (model->skinscenes[s].framecount > 1)
1432 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1434 s = model->skinscenes[s].firstframe;
1437 t = t + s * model->num_surfaces;
1439 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];
1440 texture->currentframe = t;
1443 t->currentmaterialflags = t->basematerialflags;
1444 currentalpha = ent->alpha;
1445 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1446 currentalpha *= r_wateralpha.value;
1447 if (!(ent->flags & RENDER_LIGHT))
1448 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1449 if (ent->effects & EF_ADDITIVE)
1450 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1451 else if (currentalpha < 1)
1452 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1453 if (ent->effects & EF_NODEPTHTEST)
1454 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1455 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1456 t->currenttexmatrix = r_waterscrollmatrix;
1458 t->currenttexmatrix = r_identitymatrix;
1459 t->currentnumlayers = 0;
1460 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1462 if (gl_lightmaps.integer)
1463 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1464 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1466 // transparent sky would be ridiculous
1467 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1468 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1472 int blendfunc1, blendfunc2, depthmask;
1473 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1475 blendfunc1 = GL_SRC_ALPHA;
1476 blendfunc2 = GL_ONE;
1479 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1481 blendfunc1 = GL_SRC_ALPHA;
1482 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1487 blendfunc1 = GL_ONE;
1488 blendfunc2 = GL_ZERO;
1491 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1493 rtexture_t *currentbasetexture;
1495 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1496 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1497 currentbasetexture = (ent->colormap < 0 && t->skin.merged) ? t->skin.merged : t->skin.base;
1498 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1500 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], currentalpha);
1501 if (ent->colormap >= 0 && t->skin.pants)
1502 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2], currentalpha);
1503 if (ent->colormap >= 0 && t->skin.shirt)
1504 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2], currentalpha);
1510 // q3bsp has no lightmap updates, so the lightstylevalue that
1511 // would normally be baked into the lightmaptexture must be
1512 // applied to the color
1513 if (ent->model->type == mod_brushq3)
1514 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1515 // transparent and fullbright are not affected by r_lightmapintensity
1516 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1517 colorscale *= r_lightmapintensity;
1518 if (r_textureunits.integer >= 2 && gl_combine.integer)
1519 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_COMBINE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, currentalpha);
1520 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1521 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale * 0.5f, ent->colormod[1] * colorscale * 0.5f, ent->colormod[2] * colorscale * 0.5f, currentalpha);
1523 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, currentalpha);
1524 if (r_ambient.value >= (1.0f/64.0f))
1525 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), currentalpha);
1526 if (ent->colormap >= 0 && t->skin.pants)
1528 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * colorscale, ent->colormap_pantscolor[1] * colorscale, ent->colormap_pantscolor[2] * colorscale, currentalpha);
1529 if (r_ambient.value >= (1.0f/64.0f))
1530 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * r_ambient.value * (1.0f / 64.0f), currentalpha);
1532 if (ent->colormap >= 0 && t->skin.shirt)
1534 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * colorscale, ent->colormap_shirtcolor[1] * colorscale, ent->colormap_shirtcolor[2] * colorscale, currentalpha);
1535 if (r_ambient.value >= (1.0f/64.0f))
1536 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * r_ambient.value * (1.0f / 64.0f), currentalpha);
1539 if (t->skin.glow != NULL)
1540 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, currentalpha);
1541 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1543 // if this is opaque use alpha blend which will darken the earlier
1546 // if this is an alpha blended material, all the earlier passes
1547 // were darkened by fog already, so we only need to add the fog
1548 // color ontop through the fog mask texture
1550 // if this is an additive blended material, all the earlier passes
1551 // were darkened by fog already, and we should not add fog color
1552 // (because the background was not darkened, there is no fog color
1553 // that was lost behind it).
1554 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], currentalpha);
1561 void R_UpdateAllTextureInfo(entity_render_t *ent)
1565 for (i = 0;i < ent->model->num_textures;i++)
1566 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1569 float *rsurface_vertex3f;
1570 float *rsurface_svector3f;
1571 float *rsurface_tvector3f;
1572 float *rsurface_normal3f;
1573 float *rsurface_lightmapcolor4f;
1575 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1578 float center[3], forward[3], right[3], up[3], v[4][3];
1579 matrix4x4_t matrix1, imatrix1;
1580 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1582 rsurface_vertex3f = varray_vertex3f;
1583 rsurface_svector3f = NULL;
1584 rsurface_tvector3f = NULL;
1585 rsurface_normal3f = NULL;
1586 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1590 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1591 rsurface_svector3f = surface->groupmesh->data_svector3f;
1592 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1593 rsurface_normal3f = surface->groupmesh->data_normal3f;
1595 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1597 if (!rsurface_svector3f)
1599 rsurface_svector3f = varray_svector3f;
1600 rsurface_tvector3f = varray_tvector3f;
1601 rsurface_normal3f = varray_normal3f;
1602 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);
1604 // a single autosprite surface can contain multiple sprites...
1605 VectorClear(forward);
1607 VectorSet(up, 0, 0, 1);
1608 for (j = 0;j < surface->num_vertices - 3;j += 4)
1610 VectorClear(center);
1611 for (i = 0;i < 4;i++)
1612 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1613 VectorScale(center, 0.25f, center);
1614 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1615 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);
1616 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1617 for (i = 0;i < 4;i++)
1618 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1619 forward[0] = modelorg[0] - center[0];
1620 forward[1] = modelorg[1] - center[1];
1621 VectorNormalize(forward);
1622 right[0] = forward[1];
1623 right[1] = -forward[0];
1624 for (i = 0;i < 4;i++)
1625 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1627 rsurface_vertex3f = varray_vertex3f;
1628 rsurface_svector3f = NULL;
1629 rsurface_tvector3f = NULL;
1630 rsurface_normal3f = NULL;
1632 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1634 if (!rsurface_svector3f)
1636 rsurface_svector3f = varray_svector3f;
1637 rsurface_tvector3f = varray_tvector3f;
1638 rsurface_normal3f = varray_normal3f;
1639 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);
1641 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1642 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1643 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1644 // a single autosprite surface can contain multiple sprites...
1645 for (j = 0;j < surface->num_vertices - 3;j += 4)
1647 VectorClear(center);
1648 for (i = 0;i < 4;i++)
1649 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1650 VectorScale(center, 0.25f, center);
1651 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1652 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);
1653 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1654 for (i = 0;i < 4;i++)
1655 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1656 for (i = 0;i < 4;i++)
1657 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1659 rsurface_vertex3f = varray_vertex3f;
1660 rsurface_svector3f = NULL;
1661 rsurface_tvector3f = NULL;
1662 rsurface_normal3f = NULL;
1664 R_Mesh_VertexPointer(rsurface_vertex3f);
1667 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)
1675 vec4_t ambientcolor4f;
1676 vec3_t diffusecolor;
1677 vec3_t diffusenormal;
1678 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1680 rsurface_lightmapcolor4f = varray_color4f;
1681 if (rsurface_normal3f == NULL)
1683 rsurface_normal3f = varray_normal3f;
1684 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);
1686 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);
1695 r = ambientcolor4f[0];
1696 g = ambientcolor4f[1];
1697 b = ambientcolor4f[2];
1698 a = ambientcolor4f[3];
1699 rsurface_lightmapcolor4f = NULL;
1702 else if (lightmode >= 1)
1704 if (surface->lightmapinfo)
1706 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1708 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1711 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1712 VectorScale(lm, scale, c);
1713 if (surface->lightmapinfo->styles[1] != 255)
1715 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1717 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1718 VectorMA(c, scale, lm, c);
1719 if (surface->lightmapinfo->styles[2] != 255)
1722 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1723 VectorMA(c, scale, lm, c);
1724 if (surface->lightmapinfo->styles[3] != 255)
1727 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1728 VectorMA(c, scale, lm, c);
1736 rsurface_lightmapcolor4f = varray_color4f;
1739 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1742 rsurface_lightmapcolor4f = NULL;
1745 if (rsurface_lightmapcolor4f)
1747 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)
1749 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1758 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)
1760 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1767 rsurface_lightmapcolor4f = varray_color4f;
1769 if (applycolor && rsurface_lightmapcolor4f)
1771 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)
1778 rsurface_lightmapcolor4f = varray_color4f;
1780 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1781 GL_Color(r, g, b, a);
1785 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1787 int texturesurfaceindex;
1789 const msurface_t *surface;
1790 qboolean applycolor;
1792 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1794 renderstats.entities_surfaces += texturenumsurfaces;
1795 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1796 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1797 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1798 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1799 qglDisable(GL_CULL_FACE);
1800 if (texture->currentnumlayers)
1803 texturelayer_t *layer;
1804 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1807 int layertexrgbscale;
1808 GL_DepthMask(layer->depthmask);
1809 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1810 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1812 layertexrgbscale = 4;
1813 VectorScale(layer->color, 0.25f, layercolor);
1815 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
1817 layertexrgbscale = 2;
1818 VectorScale(layer->color, 0.5f, layercolor);
1822 layertexrgbscale = 1;
1823 VectorScale(layer->color, 1.0f, layercolor);
1825 layercolor[3] = layer->color[3];
1826 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1827 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
1828 switch (layer->type)
1830 case TEXTURELAYERTYPE_SKY:
1833 skyrendernow = false;
1834 if (skyrendermasked)
1837 // restore entity matrix and GL_Color
1838 R_Mesh_Matrix(&ent->matrix);
1839 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1842 // LordHavoc: HalfLife maps have freaky skypolys...
1843 //if (!ent->model->brush.ishlbsp)
1845 if (skyrendermasked)
1847 // depth-only (masking)
1848 GL_ColorMask(0,0,0,0);
1849 // just to make sure that braindead drivers don't draw anything
1850 // despite that colormask...
1851 GL_BlendFunc(GL_ZERO, GL_ONE);
1856 GL_BlendFunc(GL_ONE, GL_ZERO);
1858 memset(&m, 0, sizeof(m));
1860 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1862 surface = texturesurfacelist[texturesurfaceindex];
1863 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1864 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1865 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1866 GL_LockArrays(0, 0);
1868 if (skyrendermasked)
1869 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1872 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
1873 memset(&m, 0, sizeof(m));
1874 m.tex[1] = R_GetTexture(layer->texture);
1875 m.texmatrix[1] = layer->texmatrix;
1876 m.texrgbscale[1] = layertexrgbscale;
1877 m.pointer_color = varray_color4f;
1879 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1881 surface = texturesurfacelist[texturesurfaceindex];
1882 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1883 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1884 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1887 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1888 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1890 else if (surface->lightmaptexture)
1892 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1893 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1897 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1898 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1900 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1901 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1902 GL_LockArrays(0, 0);
1905 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
1906 memset(&m, 0, sizeof(m));
1907 m.tex[0] = R_GetTexture(layer->texture);
1908 m.texmatrix[0] = layer->texmatrix;
1909 m.pointer_color = varray_color4f;
1910 m.texrgbscale[0] = layertexrgbscale;
1912 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1914 surface = texturesurfacelist[texturesurfaceindex];
1915 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1916 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1919 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1920 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
1922 else if (surface->lightmaptexture)
1924 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1925 R_Mesh_ColorPointer(NULL);
1929 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1930 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
1932 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1933 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1934 GL_LockArrays(0, 0);
1936 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1937 memset(&m, 0, sizeof(m));
1938 m.tex[0] = R_GetTexture(layer->texture);
1939 m.texmatrix[0] = layer->texmatrix;
1940 m.pointer_color = varray_color4f;
1941 m.texrgbscale[0] = layertexrgbscale;
1943 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1945 surface = texturesurfacelist[texturesurfaceindex];
1946 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1947 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1948 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1949 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1950 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1951 GL_LockArrays(0, 0);
1954 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
1955 memset(&m, 0, sizeof(m));
1956 m.tex[0] = R_GetTexture(layer->texture);
1957 m.texmatrix[0] = layer->texmatrix;
1958 m.texrgbscale[0] = layertexrgbscale;
1959 m.pointer_color = varray_color4f;
1961 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1963 surface = texturesurfacelist[texturesurfaceindex];
1964 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1965 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1966 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1967 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1968 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1969 GL_LockArrays(0, 0);
1972 case TEXTURELAYERTYPE_TEXTURE:
1973 memset(&m, 0, sizeof(m));
1974 m.tex[0] = R_GetTexture(layer->texture);
1975 m.texmatrix[0] = layer->texmatrix;
1976 m.pointer_color = varray_color4f;
1977 m.texrgbscale[0] = layertexrgbscale;
1979 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1981 surface = texturesurfacelist[texturesurfaceindex];
1982 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1983 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1984 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1985 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1986 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1987 GL_LockArrays(0, 0);
1990 case TEXTURELAYERTYPE_FOG:
1991 memset(&m, 0, sizeof(m));
1994 m.tex[0] = R_GetTexture(layer->texture);
1995 m.texmatrix[0] = layer->texmatrix;
1998 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2002 surface = texturesurfacelist[texturesurfaceindex];
2003 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2005 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2006 R_Mesh_ColorPointer(varray_color4f);
2007 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)
2009 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2010 c[0] = layercolor[0];
2011 c[1] = layercolor[1];
2012 c[2] = layercolor[2];
2013 c[3] = f * layercolor[3];
2015 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2016 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2017 GL_LockArrays(0, 0);
2021 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2023 // if trying to do overbright on first pass of an opaque surface
2024 // when combine is not supported, brighten as a post process
2025 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2028 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2029 GL_Color(1, 1, 1, 1);
2030 memset(&m, 0, sizeof(m));
2032 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2034 surface = texturesurfacelist[texturesurfaceindex];
2035 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2036 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2037 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2038 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2039 GL_LockArrays(0, 0);
2044 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2045 qglEnable(GL_CULL_FACE);
2048 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2050 const entity_render_t *ent = (entity_render_t *)calldata1;
2051 const msurface_t *surface = ent->model->data_surfaces + calldata2;
2055 texture = surface->texture;
2056 if (texture->basematerialflags & MATERIALFLAG_SKY)
2057 return; // transparent sky is too difficult
2058 R_UpdateTextureInfo(ent, texture);
2060 R_Mesh_Matrix(&ent->matrix);
2061 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2062 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2065 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2067 int texturesurfaceindex;
2068 const msurface_t *surface;
2069 vec3_t tempcenter, center;
2070 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2072 // drawing sky transparently would be too difficult
2073 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2075 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2077 surface = texturesurfacelist[texturesurfaceindex];
2078 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2079 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2080 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2081 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2082 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2087 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2090 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2091 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2093 int i, j, f, flagsmask;
2094 int counttriangles = 0;
2095 msurface_t *surface, **surfacechain;
2096 texture_t *t, *texture;
2097 model_t *model = ent->model;
2099 const int maxsurfacelist = 1024;
2100 int numsurfacelist = 0;
2101 const msurface_t *surfacelist[1024];
2104 R_Mesh_Matrix(&ent->matrix);
2105 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2107 // update light styles
2108 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2110 for (i = 0;i < model->brushq1.light_styles;i++)
2112 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2114 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2115 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2116 for (;(surface = *surfacechain);surfacechain++)
2117 surface->cached_dlight = true;
2122 R_UpdateAllTextureInfo(ent);
2123 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2128 if (ent == r_refdef.worldentity)
2130 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2132 if (!r_worldsurfacevisible[j])
2134 if (t != surface->texture)
2138 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2141 t = surface->texture;
2142 texture = t->currentframe;
2143 f = texture->currentmaterialflags & flagsmask;
2145 if (f && surface->num_triangles)
2147 // if lightmap parameters changed, rebuild lightmap texture
2148 if (surface->cached_dlight && surface->lightmapinfo->samples)
2149 R_BuildLightMap(ent, surface);
2150 // add face to draw list
2151 surfacelist[numsurfacelist++] = surface;
2152 counttriangles += surface->num_triangles;
2153 if (numsurfacelist >= maxsurfacelist)
2155 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2163 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2165 if (t != surface->texture)
2169 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2172 t = surface->texture;
2173 texture = t->currentframe;
2174 f = texture->currentmaterialflags & flagsmask;
2176 if (f && surface->num_triangles)
2178 // if lightmap parameters changed, rebuild lightmap texture
2179 if (surface->cached_dlight && surface->lightmapinfo->samples)
2180 R_BuildLightMap(ent, surface);
2181 // add face to draw list
2182 surfacelist[numsurfacelist++] = surface;
2183 counttriangles += surface->num_triangles;
2184 if (numsurfacelist >= maxsurfacelist)
2186 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2193 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2194 if (!r_showtrispass)
2195 renderstats.entities_triangles += counttriangles;