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)
749 int screenwidth, screenheight;
754 // set the (poorly named) screenwidth and screenheight variables to
755 // a power of 2 at least as large as the screen, these will define the
756 // size of the texture to allocate
757 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
758 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
760 doblend = r_refdef.viewblend[3] >= 0.01f;
761 dobloom = r_bloom.integer && screenwidth <= gl_max_texture_size && screenheight <= gl_max_texture_size && 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;
763 if (!dobloom && !doblend)
766 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
769 R_Mesh_Matrix(&r_identitymatrix);
770 // vertex coordinates for a quad that covers the screen exactly
771 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
772 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
773 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
774 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
777 int bloomwidth, bloomheight, x, dobloomblend, range;
778 float xoffset, yoffset, r;
780 // allocate textures as needed
781 if (!r_bloom_texture_screen)
782 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
783 if (!r_bloom_texture_bloom)
784 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
785 // set bloomwidth and bloomheight to the bloom resolution that will be
786 // used (often less than the screen resolution for faster rendering)
787 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
788 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
789 // set up a texcoord array for the full resolution screen image
790 // (we have to keep this around to copy back during final render)
791 varray_texcoord2f[0][0] = 0;
792 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
793 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
794 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
795 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
796 varray_texcoord2f[0][5] = 0;
797 varray_texcoord2f[0][6] = 0;
798 varray_texcoord2f[0][7] = 0;
799 // set up a texcoord array for the reduced resolution bloom image
800 // (which will be additive blended over the screen image)
801 varray_texcoord2f[1][0] = 0;
802 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
803 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
804 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
805 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
806 varray_texcoord2f[1][5] = 0;
807 varray_texcoord2f[1][6] = 0;
808 varray_texcoord2f[1][7] = 0;
809 memset(&m, 0, sizeof(m));
810 m.pointer_vertex = varray_vertex3f;
811 m.pointer_texcoord[0] = varray_texcoord2f[0];
812 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
814 // copy view into the full resolution screen image texture
816 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
817 renderstats.bloom_copypixels += r_view_width * r_view_height;
818 // now scale it down to the bloom size and raise to a power of itself
819 // to darken it (this leaves the really bright stuff bright, and
820 // everything else becomes very dark)
821 // TODO: optimize with multitexture or GLSL
822 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
823 GL_BlendFunc(GL_ONE, GL_ZERO);
824 GL_Color(1, 1, 1, 1);
825 R_Mesh_Draw(0, 4, 2, polygonelements);
826 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
827 // render multiple times with a multiply blendfunc to raise to a power
828 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
829 for (x = 1;x < r_bloom_power.integer;x++)
831 R_Mesh_Draw(0, 4, 2, polygonelements);
832 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
834 // we now have a darkened bloom image in the framebuffer, copy it into
835 // the bloom image texture for more processing
836 memset(&m, 0, sizeof(m));
837 m.pointer_vertex = varray_vertex3f;
838 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
839 m.pointer_texcoord[0] = varray_texcoord2f[2];
842 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
843 renderstats.bloom_copypixels += bloomwidth * bloomheight;
844 // blend on at multiple vertical offsets to achieve a vertical blur
845 // TODO: do offset blends using GLSL
846 range = r_bloom_blur.integer * bloomwidth / 320;
847 GL_BlendFunc(GL_ONE, GL_ZERO);
848 for (x = -range;x <= range;x++)
850 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
851 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
852 // compute a texcoord array with the specified x and y offset
853 varray_texcoord2f[2][0] = xoffset+0;
854 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
855 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
856 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
857 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
858 varray_texcoord2f[2][5] = yoffset+0;
859 varray_texcoord2f[2][6] = xoffset+0;
860 varray_texcoord2f[2][7] = yoffset+0;
861 // this r value looks like a 'dot' particle, fading sharply to
862 // black at the edges
863 // (probably not realistic but looks good enough)
864 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
867 GL_Color(r, r, r, 1);
868 R_Mesh_Draw(0, 4, 2, polygonelements);
869 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
870 GL_BlendFunc(GL_ONE, GL_ONE);
872 // copy the vertically blurred bloom view to a texture
874 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
875 renderstats.bloom_copypixels += bloomwidth * bloomheight;
876 // blend the vertically blurred image at multiple offsets horizontally
877 // to finish the blur effect
878 // TODO: do offset blends using GLSL
879 range = r_bloom_blur.integer * bloomwidth / 320;
880 GL_BlendFunc(GL_ONE, GL_ZERO);
881 for (x = -range;x <= range;x++)
883 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
884 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
885 // compute a texcoord array with the specified x and y offset
886 varray_texcoord2f[2][0] = xoffset+0;
887 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
888 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
889 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
890 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
891 varray_texcoord2f[2][5] = yoffset+0;
892 varray_texcoord2f[2][6] = xoffset+0;
893 varray_texcoord2f[2][7] = yoffset+0;
894 // this r value looks like a 'dot' particle, fading sharply to
895 // black at the edges
896 // (probably not realistic but looks good enough)
897 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
900 GL_Color(r, r, r, 1);
901 R_Mesh_Draw(0, 4, 2, polygonelements);
902 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
903 GL_BlendFunc(GL_ONE, GL_ONE);
905 // copy the blurred bloom view to a texture
907 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
908 renderstats.bloom_copypixels += bloomwidth * bloomheight;
909 // go back to full view area
910 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
911 // put the original screen image back in place and blend the bloom
913 memset(&m, 0, sizeof(m));
914 m.pointer_vertex = varray_vertex3f;
915 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
916 m.pointer_texcoord[0] = varray_texcoord2f[0];
918 dobloomblend = false;
920 // do both in one pass if possible
921 if (r_textureunits.integer >= 2 && gl_combine.integer)
923 dobloomblend = false;
924 m.texcombinergb[1] = GL_ADD;
925 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
926 m.pointer_texcoord[1] = varray_texcoord2f[1];
932 GL_BlendFunc(GL_ONE, GL_ZERO);
934 R_Mesh_Draw(0, 4, 2, polygonelements);
935 renderstats.bloom_drawpixels += r_view_width * r_view_height;
936 // now blend on the bloom texture if multipass
939 memset(&m, 0, sizeof(m));
940 m.pointer_vertex = varray_vertex3f;
941 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
942 m.pointer_texcoord[0] = varray_texcoord2f[1];
944 GL_BlendFunc(GL_ONE, GL_ONE);
946 R_Mesh_Draw(0, 4, 2, polygonelements);
947 renderstats.bloom_drawpixels += r_view_width * r_view_height;
952 // apply a color tint to the whole view
953 memset(&m, 0, sizeof(m));
954 m.pointer_vertex = varray_vertex3f;
956 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
957 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
958 R_Mesh_Draw(0, 4, 2, polygonelements);
962 void R_RenderScene(void);
964 matrix4x4_t r_waterscrollmatrix;
971 void R_RenderView(void)
973 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
974 return; //Host_Error ("R_RenderView: NULL worldmodel");
976 r_view_width = bound(0, r_refdef.width, vid.width);
977 r_view_height = bound(0, r_refdef.height, vid.height);
979 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
980 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
982 r_view_fov_x = bound(1, r_refdef.fov_x, 170);
983 r_view_fov_y = bound(1, r_refdef.fov_y, 170);
984 r_view_matrix = r_refdef.viewentitymatrix;
985 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
986 r_rtworld = r_shadow_realtime_world.integer;
987 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
988 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
989 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
990 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
992 // GL is weird because it's bottom to top, r_view_y is top to bottom
993 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
994 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
995 GL_ScissorTest(true);
1000 R_TimeReport("setup");
1002 qglDepthFunc(GL_LEQUAL);
1003 qglPolygonOffset(0, 0);
1004 qglEnable(GL_POLYGON_OFFSET_FILL);
1008 qglPolygonOffset(0, 0);
1009 qglDisable(GL_POLYGON_OFFSET_FILL);
1012 R_TimeReport("blendview");
1014 GL_Scissor(0, 0, vid.width, vid.height);
1015 GL_ScissorTest(false);
1018 extern void R_DrawLightningBeams (void);
1019 void R_RenderScene(void)
1021 // don't let sound skip if going slow
1022 if (r_refdef.extraupdate)
1027 R_MeshQueue_BeginScene();
1029 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1033 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1034 if (r_rtworldshadows || r_rtdlightshadows)
1035 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
1037 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
1039 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1041 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);
1045 R_WorldVisibility();
1046 R_TimeReport("worldvis");
1049 R_TimeReport("markentity");
1051 R_Shadow_UpdateWorldLightSelection();
1053 // don't let sound skip if going slow
1054 if (r_refdef.extraupdate)
1057 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1058 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1060 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1061 R_TimeReport("worldsky");
1064 if (R_DrawBrushModelsSky())
1065 R_TimeReport("bmodelsky");
1067 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1068 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1070 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1071 R_TimeReport("world");
1074 // don't let sound skip if going slow
1075 if (r_refdef.extraupdate)
1078 GL_ShowTrisColor(0, 0.015, 0, 1);
1081 R_TimeReport("models");
1083 // don't let sound skip if going slow
1084 if (r_refdef.extraupdate)
1087 GL_ShowTrisColor(0, 0, 0.033, 1);
1088 R_ShadowVolumeLighting(false);
1089 R_TimeReport("rtlights");
1091 // don't let sound skip if going slow
1092 if (r_refdef.extraupdate)
1095 GL_ShowTrisColor(0.1, 0, 0, 1);
1097 R_DrawLightningBeams();
1098 R_TimeReport("lightning");
1101 R_TimeReport("particles");
1104 R_TimeReport("explosions");
1106 R_MeshQueue_RenderTransparent();
1107 R_TimeReport("drawtrans");
1110 R_TimeReport("coronas");
1112 R_DrawWorldCrosshair();
1113 R_TimeReport("crosshair");
1115 R_MeshQueue_Render();
1116 R_MeshQueue_EndScene();
1118 if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1120 R_ShadowVolumeLighting(true);
1121 R_TimeReport("visiblevolume");
1124 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1126 // don't let sound skip if going slow
1127 if (r_refdef.extraupdate)
1132 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1135 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1137 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1138 GL_DepthMask(false);
1140 R_Mesh_Matrix(&r_identitymatrix);
1142 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1143 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1144 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1145 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1146 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1147 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1148 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1149 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1150 R_FillColors(color, 8, cr, cg, cb, ca);
1153 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1155 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1157 c[0] = c[0] * f1 + fogcolor[0] * f2;
1158 c[1] = c[1] * f1 + fogcolor[1] * f2;
1159 c[2] = c[2] * f1 + fogcolor[2] * f2;
1162 memset(&m, 0, sizeof(m));
1163 m.pointer_vertex = vertex3f;
1164 m.pointer_color = color;
1170 int nomodelelements[24] =
1182 float nomodelvertex3f[6*3] =
1192 float nomodelcolor4f[6*4] =
1194 0.0f, 0.0f, 0.5f, 1.0f,
1195 0.0f, 0.0f, 0.5f, 1.0f,
1196 0.0f, 0.5f, 0.0f, 1.0f,
1197 0.0f, 0.5f, 0.0f, 1.0f,
1198 0.5f, 0.0f, 0.0f, 1.0f,
1199 0.5f, 0.0f, 0.0f, 1.0f
1202 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1204 const entity_render_t *ent = (entity_render_t *)calldata1;
1209 R_Mesh_Matrix(&ent->matrix);
1211 memset(&m, 0, sizeof(m));
1212 m.pointer_vertex = nomodelvertex3f;
1214 if (ent->flags & EF_ADDITIVE)
1216 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1217 GL_DepthMask(false);
1219 else if (ent->alpha < 1)
1221 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1222 GL_DepthMask(false);
1226 GL_BlendFunc(GL_ONE, GL_ZERO);
1229 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1232 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1233 m.pointer_color = color4f;
1234 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1236 for (i = 0, c = color4f;i < 6;i++, c += 4)
1238 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1239 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1240 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1244 else if (ent->alpha != 1)
1246 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1247 m.pointer_color = color4f;
1248 for (i = 0, c = color4f;i < 6;i++, c += 4)
1252 m.pointer_color = nomodelcolor4f;
1254 R_Mesh_Draw(0, 6, 8, nomodelelements);
1257 void R_DrawNoModel(entity_render_t *ent)
1259 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1260 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1262 // R_DrawNoModelCallback(ent, 0);
1265 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1267 vec3_t right1, right2, diff, normal;
1269 VectorSubtract (org2, org1, normal);
1271 // calculate 'right' vector for start
1272 VectorSubtract (r_vieworigin, org1, diff);
1273 CrossProduct (normal, diff, right1);
1274 VectorNormalize (right1);
1276 // calculate 'right' vector for end
1277 VectorSubtract (r_vieworigin, org2, diff);
1278 CrossProduct (normal, diff, right2);
1279 VectorNormalize (right2);
1281 vert[ 0] = org1[0] + width * right1[0];
1282 vert[ 1] = org1[1] + width * right1[1];
1283 vert[ 2] = org1[2] + width * right1[2];
1284 vert[ 3] = org1[0] - width * right1[0];
1285 vert[ 4] = org1[1] - width * right1[1];
1286 vert[ 5] = org1[2] - width * right1[2];
1287 vert[ 6] = org2[0] - width * right2[0];
1288 vert[ 7] = org2[1] - width * right2[1];
1289 vert[ 8] = org2[2] - width * right2[2];
1290 vert[ 9] = org2[0] + width * right2[0];
1291 vert[10] = org2[1] + width * right2[1];
1292 vert[11] = org2[2] + width * right2[2];
1295 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1297 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)
1299 float fog = 0.0f, ifog;
1303 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1306 R_Mesh_Matrix(&r_identitymatrix);
1307 GL_BlendFunc(blendfunc1, blendfunc2);
1308 GL_DepthMask(false);
1309 GL_DepthTest(!depthdisable);
1311 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1312 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1313 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1314 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1315 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1316 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1317 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1318 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1319 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1320 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1321 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1322 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1324 memset(&m, 0, sizeof(m));
1325 m.tex[0] = R_GetTexture(texture);
1326 m.pointer_texcoord[0] = spritetexcoord2f;
1327 m.pointer_vertex = varray_vertex3f;
1329 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
1330 R_Mesh_Draw(0, 4, 2, polygonelements);
1332 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
1334 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
1335 GL_BlendFunc(blendfunc1, GL_ONE);
1336 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
1337 R_Mesh_Draw(0, 4, 2, polygonelements);
1341 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1345 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1346 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1348 if (i == mesh->numvertices)
1350 if (mesh->numvertices < mesh->maxvertices)
1352 VectorCopy(v, vertex3f);
1353 mesh->numvertices++;
1355 return mesh->numvertices;
1361 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1365 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1366 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1367 e = mesh->element3i + mesh->numtriangles * 3;
1368 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1370 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1371 if (mesh->numtriangles < mesh->maxtriangles)
1376 mesh->numtriangles++;
1378 element[1] = element[2];
1382 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1384 int planenum, planenum2;
1387 mplane_t *plane, *plane2;
1388 float temppoints[2][256*3];
1389 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1393 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1394 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1396 if (planenum2 == planenum)
1398 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);
1401 if (tempnumpoints < 3)
1403 // generate elements forming a triangle fan for this polygon
1404 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1408 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)
1410 texturelayer_t *layer;
1411 layer = t->currentlayers + t->currentnumlayers++;
1413 layer->depthmask = depthmask;
1414 layer->blendfunc1 = blendfunc1;
1415 layer->blendfunc2 = blendfunc2;
1416 layer->texture = texture;
1417 layer->texmatrix = *matrix;
1418 layer->color[0] = r;
1419 layer->color[1] = g;
1420 layer->color[2] = b;
1421 layer->color[3] = a;
1424 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1426 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1427 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1431 texture_t *texture = t;
1432 model_t *model = ent->model;
1433 int s = ent->skinnum;
1434 if ((unsigned int)s >= (unsigned int)model->numskins)
1436 if (model->skinscenes)
1438 if (model->skinscenes[s].framecount > 1)
1439 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1441 s = model->skinscenes[s].firstframe;
1444 t = t + s * model->num_surfaces;
1446 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];
1447 texture->currentframe = t;
1450 t->currentmaterialflags = t->basematerialflags;
1451 currentalpha = ent->alpha;
1452 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1453 currentalpha *= r_wateralpha.value;
1454 if (!(ent->flags & RENDER_LIGHT))
1455 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1456 if (ent->effects & EF_ADDITIVE)
1457 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1458 else if (currentalpha < 1)
1459 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1460 if (ent->effects & EF_NODEPTHTEST)
1461 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1462 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1463 t->currenttexmatrix = r_waterscrollmatrix;
1465 t->currenttexmatrix = r_identitymatrix;
1466 t->currentnumlayers = 0;
1467 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
1469 if (gl_lightmaps.integer)
1470 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &r_identitymatrix, 1, 1, 1, 1);
1471 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
1473 // transparent sky would be ridiculous
1474 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1475 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &r_identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
1479 int blendfunc1, blendfunc2, depthmask;
1480 if (t->currentmaterialflags & MATERIALFLAG_ADD)
1482 blendfunc1 = GL_SRC_ALPHA;
1483 blendfunc2 = GL_ONE;
1486 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
1488 blendfunc1 = GL_SRC_ALPHA;
1489 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
1494 blendfunc1 = GL_ONE;
1495 blendfunc2 = GL_ZERO;
1498 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1500 rtexture_t *currentbasetexture;
1502 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1503 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
1504 currentbasetexture = (ent->colormap < 0 && t->skin.merged) ? t->skin.merged : t->skin.base;
1505 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1507 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], currentalpha);
1508 if (ent->colormap >= 0 && t->skin.pants)
1509 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);
1510 if (ent->colormap >= 0 && t->skin.shirt)
1511 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);
1517 // q3bsp has no lightmap updates, so the lightstylevalue that
1518 // would normally be baked into the lightmaptexture must be
1519 // applied to the color
1520 if (ent->model->type == mod_brushq3)
1521 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
1522 // transparent and fullbright are not affected by r_lightmapintensity
1523 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1524 colorscale *= r_lightmapintensity;
1525 if (r_textureunits.integer >= 2 && gl_combine.integer)
1526 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);
1527 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
1528 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);
1530 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);
1531 if (r_ambient.value >= (1.0f/64.0f))
1532 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);
1533 if (ent->colormap >= 0 && t->skin.pants)
1535 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);
1536 if (r_ambient.value >= (1.0f/64.0f))
1537 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);
1539 if (ent->colormap >= 0 && t->skin.shirt)
1541 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);
1542 if (r_ambient.value >= (1.0f/64.0f))
1543 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);
1546 if (t->skin.glow != NULL)
1547 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, currentalpha);
1548 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
1550 // if this is opaque use alpha blend which will darken the earlier
1553 // if this is an alpha blended material, all the earlier passes
1554 // were darkened by fog already, so we only need to add the fog
1555 // color ontop through the fog mask texture
1557 // if this is an additive blended material, all the earlier passes
1558 // were darkened by fog already, and we should not add fog color
1559 // (because the background was not darkened, there is no fog color
1560 // that was lost behind it).
1561 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);
1568 void R_UpdateAllTextureInfo(entity_render_t *ent)
1572 for (i = 0;i < ent->model->num_textures;i++)
1573 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1576 float *rsurface_vertex3f;
1577 float *rsurface_svector3f;
1578 float *rsurface_tvector3f;
1579 float *rsurface_normal3f;
1580 float *rsurface_lightmapcolor4f;
1582 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1585 float center[3], forward[3], right[3], up[3], v[4][3];
1586 matrix4x4_t matrix1, imatrix1;
1587 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1589 rsurface_vertex3f = varray_vertex3f;
1590 rsurface_svector3f = NULL;
1591 rsurface_tvector3f = NULL;
1592 rsurface_normal3f = NULL;
1593 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1597 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1598 rsurface_svector3f = surface->groupmesh->data_svector3f;
1599 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1600 rsurface_normal3f = surface->groupmesh->data_normal3f;
1602 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1604 if (!rsurface_svector3f)
1606 rsurface_svector3f = varray_svector3f;
1607 rsurface_tvector3f = varray_tvector3f;
1608 rsurface_normal3f = varray_normal3f;
1609 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);
1611 // a single autosprite surface can contain multiple sprites...
1612 VectorClear(forward);
1614 VectorSet(up, 0, 0, 1);
1615 for (j = 0;j < surface->num_vertices - 3;j += 4)
1617 VectorClear(center);
1618 for (i = 0;i < 4;i++)
1619 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1620 VectorScale(center, 0.25f, center);
1621 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1622 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);
1623 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1624 for (i = 0;i < 4;i++)
1625 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1626 forward[0] = modelorg[0] - center[0];
1627 forward[1] = modelorg[1] - center[1];
1628 VectorNormalize(forward);
1629 right[0] = forward[1];
1630 right[1] = -forward[0];
1631 for (i = 0;i < 4;i++)
1632 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1634 rsurface_vertex3f = varray_vertex3f;
1635 rsurface_svector3f = NULL;
1636 rsurface_tvector3f = NULL;
1637 rsurface_normal3f = NULL;
1639 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1641 if (!rsurface_svector3f)
1643 rsurface_svector3f = varray_svector3f;
1644 rsurface_tvector3f = varray_tvector3f;
1645 rsurface_normal3f = varray_normal3f;
1646 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);
1648 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1649 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1650 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1651 // a single autosprite surface can contain multiple sprites...
1652 for (j = 0;j < surface->num_vertices - 3;j += 4)
1654 VectorClear(center);
1655 for (i = 0;i < 4;i++)
1656 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1657 VectorScale(center, 0.25f, center);
1658 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1659 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);
1660 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1661 for (i = 0;i < 4;i++)
1662 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1663 for (i = 0;i < 4;i++)
1664 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1666 rsurface_vertex3f = varray_vertex3f;
1667 rsurface_svector3f = NULL;
1668 rsurface_tvector3f = NULL;
1669 rsurface_normal3f = NULL;
1671 R_Mesh_VertexPointer(rsurface_vertex3f);
1674 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)
1682 vec4_t ambientcolor4f;
1683 vec3_t diffusecolor;
1684 vec3_t diffusenormal;
1685 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1687 rsurface_lightmapcolor4f = varray_color4f;
1688 if (rsurface_normal3f == NULL)
1690 rsurface_normal3f = varray_normal3f;
1691 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);
1693 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);
1702 r = ambientcolor4f[0];
1703 g = ambientcolor4f[1];
1704 b = ambientcolor4f[2];
1705 a = ambientcolor4f[3];
1706 rsurface_lightmapcolor4f = NULL;
1709 else if (lightmode >= 1)
1711 if (surface->lightmapinfo)
1713 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1715 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1718 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1719 VectorScale(lm, scale, c);
1720 if (surface->lightmapinfo->styles[1] != 255)
1722 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1724 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1725 VectorMA(c, scale, lm, c);
1726 if (surface->lightmapinfo->styles[2] != 255)
1729 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1730 VectorMA(c, scale, lm, c);
1731 if (surface->lightmapinfo->styles[3] != 255)
1734 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1735 VectorMA(c, scale, lm, c);
1743 rsurface_lightmapcolor4f = varray_color4f;
1746 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1749 rsurface_lightmapcolor4f = NULL;
1752 if (rsurface_lightmapcolor4f)
1754 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)
1756 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1765 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)
1767 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
1774 rsurface_lightmapcolor4f = varray_color4f;
1776 if (applycolor && rsurface_lightmapcolor4f)
1778 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)
1785 rsurface_lightmapcolor4f = varray_color4f;
1787 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1788 GL_Color(r, g, b, a);
1792 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1794 int texturesurfaceindex;
1796 const msurface_t *surface;
1797 qboolean applycolor;
1799 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1801 renderstats.entities_surfaces += texturenumsurfaces;
1802 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
1803 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
1804 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1805 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1806 qglDisable(GL_CULL_FACE);
1807 if (texture->currentnumlayers)
1810 texturelayer_t *layer;
1811 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
1814 int layertexrgbscale;
1815 GL_DepthMask(layer->depthmask);
1816 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
1817 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
1819 layertexrgbscale = 4;
1820 VectorScale(layer->color, 0.25f, layercolor);
1822 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
1824 layertexrgbscale = 2;
1825 VectorScale(layer->color, 0.5f, layercolor);
1829 layertexrgbscale = 1;
1830 VectorScale(layer->color, 1.0f, layercolor);
1832 layercolor[3] = layer->color[3];
1833 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1834 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
1835 switch (layer->type)
1837 case TEXTURELAYERTYPE_SKY:
1840 skyrendernow = false;
1841 if (skyrendermasked)
1844 // restore entity matrix and GL_Color
1845 R_Mesh_Matrix(&ent->matrix);
1846 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
1849 // LordHavoc: HalfLife maps have freaky skypolys...
1850 //if (!ent->model->brush.ishlbsp)
1852 if (skyrendermasked)
1854 // depth-only (masking)
1855 GL_ColorMask(0,0,0,0);
1856 // just to make sure that braindead drivers don't draw anything
1857 // despite that colormask...
1858 GL_BlendFunc(GL_ZERO, GL_ONE);
1863 GL_BlendFunc(GL_ONE, GL_ZERO);
1865 memset(&m, 0, sizeof(m));
1867 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1869 surface = texturesurfacelist[texturesurfaceindex];
1870 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1871 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1872 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1873 GL_LockArrays(0, 0);
1875 if (skyrendermasked)
1876 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1879 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
1880 memset(&m, 0, sizeof(m));
1881 m.tex[1] = R_GetTexture(layer->texture);
1882 m.texmatrix[1] = layer->texmatrix;
1883 m.texrgbscale[1] = layertexrgbscale;
1884 m.pointer_color = varray_color4f;
1886 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1888 surface = texturesurfacelist[texturesurfaceindex];
1889 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1890 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1891 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1894 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1895 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1897 else if (surface->lightmaptexture)
1899 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1900 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1904 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1905 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1907 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1908 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1909 GL_LockArrays(0, 0);
1912 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
1913 memset(&m, 0, sizeof(m));
1914 m.tex[0] = R_GetTexture(layer->texture);
1915 m.texmatrix[0] = layer->texmatrix;
1916 m.pointer_color = varray_color4f;
1917 m.texrgbscale[0] = layertexrgbscale;
1919 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1921 surface = texturesurfacelist[texturesurfaceindex];
1922 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1923 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1926 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1927 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 2, false, false);
1929 else if (surface->lightmaptexture)
1931 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1932 R_Mesh_ColorPointer(NULL);
1936 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1937 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, 1, false, false);
1939 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1940 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1941 GL_LockArrays(0, 0);
1943 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1944 memset(&m, 0, sizeof(m));
1945 m.tex[0] = R_GetTexture(layer->texture);
1946 m.texmatrix[0] = layer->texmatrix;
1947 m.pointer_color = varray_color4f;
1948 m.texrgbscale[0] = layertexrgbscale;
1950 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1952 surface = texturesurfacelist[texturesurfaceindex];
1953 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1954 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1955 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1956 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1957 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1958 GL_LockArrays(0, 0);
1961 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
1962 memset(&m, 0, sizeof(m));
1963 m.tex[0] = R_GetTexture(layer->texture);
1964 m.texmatrix[0] = layer->texmatrix;
1965 m.texrgbscale[0] = layertexrgbscale;
1966 m.pointer_color = varray_color4f;
1968 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1970 surface = texturesurfacelist[texturesurfaceindex];
1971 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1972 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1973 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode ? lightmode : 1, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1974 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1975 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1976 GL_LockArrays(0, 0);
1979 case TEXTURELAYERTYPE_TEXTURE:
1980 memset(&m, 0, sizeof(m));
1981 m.tex[0] = R_GetTexture(layer->texture);
1982 m.texmatrix[0] = layer->texmatrix;
1983 m.pointer_color = varray_color4f;
1984 m.texrgbscale[0] = layertexrgbscale;
1986 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1988 surface = texturesurfacelist[texturesurfaceindex];
1989 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1990 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1991 RSurf_SetColorPointer(ent, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, layer->flags & TEXTURELAYERFLAG_FOGDARKEN);
1992 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1993 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1994 GL_LockArrays(0, 0);
1997 case TEXTURELAYERTYPE_FOG:
1998 memset(&m, 0, sizeof(m));
2001 m.tex[0] = R_GetTexture(layer->texture);
2002 m.texmatrix[0] = layer->texmatrix;
2005 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2009 surface = texturesurfacelist[texturesurfaceindex];
2010 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2012 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2013 R_Mesh_ColorPointer(varray_color4f);
2014 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)
2016 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2017 c[0] = layercolor[0];
2018 c[1] = layercolor[1];
2019 c[2] = layercolor[2];
2020 c[3] = f * layercolor[3];
2022 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2023 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2024 GL_LockArrays(0, 0);
2028 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2030 // if trying to do overbright on first pass of an opaque surface
2031 // when combine is not supported, brighten as a post process
2032 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2035 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2036 GL_Color(1, 1, 1, 1);
2037 memset(&m, 0, sizeof(m));
2039 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2041 surface = texturesurfacelist[texturesurfaceindex];
2042 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2043 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2044 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2045 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2046 GL_LockArrays(0, 0);
2051 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2052 qglEnable(GL_CULL_FACE);
2055 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2057 const entity_render_t *ent = (entity_render_t *)calldata1;
2058 const msurface_t *surface = ent->model->data_surfaces + calldata2;
2062 texture = surface->texture;
2063 if (texture->basematerialflags & MATERIALFLAG_SKY)
2064 return; // transparent sky is too difficult
2065 R_UpdateTextureInfo(ent, texture);
2067 R_Mesh_Matrix(&ent->matrix);
2068 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2069 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2072 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2074 int texturesurfaceindex;
2075 const msurface_t *surface;
2076 vec3_t tempcenter, center;
2077 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2079 // drawing sky transparently would be too difficult
2080 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2082 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2084 surface = texturesurfacelist[texturesurfaceindex];
2085 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2086 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2087 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2088 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2089 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2094 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2097 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2098 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2100 int i, j, f, flagsmask;
2101 int counttriangles = 0;
2102 msurface_t *surface, **surfacechain;
2103 texture_t *t, *texture;
2104 model_t *model = ent->model;
2106 const int maxsurfacelist = 1024;
2107 int numsurfacelist = 0;
2108 const msurface_t *surfacelist[1024];
2111 R_Mesh_Matrix(&ent->matrix);
2112 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2114 // update light styles
2115 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2117 for (i = 0;i < model->brushq1.light_styles;i++)
2119 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2121 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2122 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2123 for (;(surface = *surfacechain);surfacechain++)
2124 surface->cached_dlight = true;
2129 R_UpdateAllTextureInfo(ent);
2130 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2135 if (ent == r_refdef.worldentity)
2137 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2139 if (!r_worldsurfacevisible[j])
2141 if (t != surface->texture)
2145 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2148 t = surface->texture;
2149 texture = t->currentframe;
2150 f = texture->currentmaterialflags & flagsmask;
2152 if (f && surface->num_triangles)
2154 // if lightmap parameters changed, rebuild lightmap texture
2155 if (surface->cached_dlight && surface->lightmapinfo->samples)
2156 R_BuildLightMap(ent, surface);
2157 // add face to draw list
2158 surfacelist[numsurfacelist++] = surface;
2159 counttriangles += surface->num_triangles;
2160 if (numsurfacelist >= maxsurfacelist)
2162 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2170 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2172 if (t != surface->texture)
2176 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2179 t = surface->texture;
2180 texture = t->currentframe;
2181 f = texture->currentmaterialflags & flagsmask;
2183 if (f && surface->num_triangles)
2185 // if lightmap parameters changed, rebuild lightmap texture
2186 if (surface->cached_dlight && surface->lightmapinfo->samples)
2187 R_BuildLightMap(ent, surface);
2188 // add face to draw list
2189 surfacelist[numsurfacelist++] = surface;
2190 counttriangles += surface->num_triangles;
2191 if (numsurfacelist >= maxsurfacelist)
2193 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2200 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2201 if (!r_showtrispass)
2202 renderstats.entities_triangles += counttriangles;