2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 // used for dlight push checking and other things
31 matrix4x4_t r_identitymatrix;
33 int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights, c_meshs, c_meshelements, c_rt_lights, c_rt_clears, c_rt_scissored, c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris, c_rtcached_shadowmeshes, c_rtcached_shadowtris, c_bloom, c_bloomcopies, c_bloomcopypixels, c_bloomdraws, c_bloomdrawpixels;
35 // true during envmap command capture
38 // maximum visible distance (recalculated from world box each frame)
40 // brightness of world lightmaps and related lighting
41 // (often reduced when world rtlights are enabled)
42 float r_lightmapintensity;
43 // whether to draw world lights realtime, dlights realtime, and their shadows
45 qboolean r_rtworldshadows;
47 qboolean r_rtdlightshadows;
50 // forces all rendering to draw triangle outlines
67 matrix4x4_t r_view_matrix;
74 // 8.8 fraction of base light value
75 unsigned short d_lightstylevalue[256];
77 cvar_t r_showtris = {0, "r_showtris", "0"};
78 cvar_t r_drawentities = {0, "r_drawentities","1"};
79 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
80 cvar_t r_speeds = {0, "r_speeds","0"};
81 cvar_t r_fullbright = {0, "r_fullbright","0"};
82 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
83 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
84 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
85 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
87 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
88 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
89 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
90 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
91 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
92 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
93 cvar_t gl_fogend = {0, "gl_fogend","0"};
95 cvar_t r_textureunits = {0, "r_textureunits", "32"};
97 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
98 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
99 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
100 cvar_t r_watershader = {CVAR_SAVE, "r_watershader", "1"};
102 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0"};
103 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "2"};
104 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "8"};
105 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
106 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"};
108 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1"};
110 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0"};
112 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
114 rtexturepool_t *r_main_texturepool;
115 rtexture_t *r_bloom_texture_screen;
116 rtexture_t *r_bloom_texture_bloom;
117 rtexture_t *r_texture_blanknormalmap;
118 rtexture_t *r_texture_white;
119 rtexture_t *r_texture_black;
120 rtexture_t *r_texture_notexture;
121 rtexture_t *r_texture_whitecube;
122 rtexture_t *r_texture_normalizationcube;
123 rtexture_t *r_texture_detailtextures[NUM_DETAILTEXTURES];
124 rtexture_t *r_texture_distorttexture[64];
126 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
129 for (i = 0;i < verts;i++)
140 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
143 for (i = 0;i < verts;i++)
155 float fog_density, fog_red, fog_green, fog_blue;
157 qboolean oldgl_fogenable;
158 void R_UpdateFog(void)
160 if (gamemode == GAME_NEHAHRA)
162 if (gl_fogenable.integer)
164 oldgl_fogenable = true;
165 fog_density = gl_fogdensity.value;
166 fog_red = gl_fogred.value;
167 fog_green = gl_foggreen.value;
168 fog_blue = gl_fogblue.value;
170 else if (oldgl_fogenable)
172 oldgl_fogenable = false;
181 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
182 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
183 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
188 fogdensity = -4000.0f / (fog_density * fog_density);
189 // fog color was already set
195 // FIXME: move this to client?
198 if (gamemode == GAME_NEHAHRA)
200 Cvar_Set("gl_fogenable", "0");
201 Cvar_Set("gl_fogdensity", "0.2");
202 Cvar_Set("gl_fogred", "0.3");
203 Cvar_Set("gl_foggreen", "0.3");
204 Cvar_Set("gl_fogblue", "0.3");
206 fog_density = fog_red = fog_green = fog_blue = 0.0f;
209 // FIXME: move this to client?
210 void FOG_registercvars(void)
212 if (gamemode == GAME_NEHAHRA)
214 Cvar_RegisterVariable (&gl_fogenable);
215 Cvar_RegisterVariable (&gl_fogdensity);
216 Cvar_RegisterVariable (&gl_fogred);
217 Cvar_RegisterVariable (&gl_foggreen);
218 Cvar_RegisterVariable (&gl_fogblue);
219 Cvar_RegisterVariable (&gl_fogstart);
220 Cvar_RegisterVariable (&gl_fogend);
224 static void R_BuildDetailTextures (void)
227 float vc[3], vx[3], vy[3], vn[3], lightdir[3];
228 #define DETAILRESOLUTION 256
229 qbyte (*data)[DETAILRESOLUTION][4];
230 qbyte (*noise)[DETAILRESOLUTION];
232 // Allocate the buffers dynamically to avoid having such big guys on the stack
233 data = Mem_Alloc(tempmempool, DETAILRESOLUTION * sizeof(*data));
234 noise = Mem_Alloc(tempmempool, DETAILRESOLUTION * sizeof(*noise));
239 VectorNormalize(lightdir);
240 for (i = 0;i < NUM_DETAILTEXTURES;i++)
242 fractalnoise(&noise[0][0], DETAILRESOLUTION, DETAILRESOLUTION >> 4);
243 for (y = 0;y < DETAILRESOLUTION;y++)
245 for (x = 0;x < DETAILRESOLUTION;x++)
249 vc[2] = noise[y][x] * (1.0f / 32.0f);
252 vx[2] = noise[y][(x + 1) % DETAILRESOLUTION] * (1.0f / 32.0f);
255 vy[2] = noise[(y + 1) % DETAILRESOLUTION][x] * (1.0f / 32.0f);
256 VectorSubtract(vx, vc, vx);
257 VectorSubtract(vy, vc, vy);
258 CrossProduct(vx, vy, vn);
260 light = 128 - DotProduct(vn, lightdir) * 128;
261 light = bound(0, light, 255);
262 data[y][x][0] = data[y][x][1] = data[y][x][2] = light;
266 r_texture_detailtextures[i] = R_LoadTexture2D(r_main_texturepool, va("detailtexture%i", i), DETAILRESOLUTION, DETAILRESOLUTION, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_PRECACHE, NULL);
273 static qbyte R_MorphDistortTexture (double y0, double y1, double y2, double y3, double morph)
275 int m = (int)(((y1 + y3 - (y0 + y2)) * morph * morph * morph) +
276 ((2 * (y0 - y1) + y2 - y3) * morph * morph) +
277 ((y2 - y0) * morph) +
279 return (qbyte)bound(0, m, 255);
282 static void R_BuildDistortTexture (void)
285 #define DISTORTRESOLUTION 32
286 qbyte data[5][DISTORTRESOLUTION][DISTORTRESOLUTION][2];
290 for (y=0; y<DISTORTRESOLUTION; y++)
292 for (x=0; x<DISTORTRESOLUTION; x++)
294 data[i][y][x][0] = rand () & 255;
295 data[i][y][x][1] = rand () & 255;
304 r_texture_distorttexture[i*16+j] = NULL;
305 if (gl_textureshader)
307 for (y=0; y<DISTORTRESOLUTION; y++)
309 for (x=0; x<DISTORTRESOLUTION; x++)
311 data[4][y][x][0] = R_MorphDistortTexture (data[(i-1)&3][y][x][0], data[i][y][x][0], data[(i+1)&3][y][x][0], data[(i+2)&3][y][x][0], 0.0625*j);
312 data[4][y][x][1] = R_MorphDistortTexture (data[(i-1)&3][y][x][1], data[i][y][x][1], data[(i+1)&3][y][x][1], data[(i+2)&3][y][x][1], 0.0625*j);
315 r_texture_distorttexture[i*16+j] = R_LoadTexture2D(r_main_texturepool, va("distorttexture%i", i*16+j), DISTORTRESOLUTION, DISTORTRESOLUTION, &data[4][0][0][0], TEXTYPE_DSDT, TEXF_PRECACHE, NULL);
321 static void R_BuildBlankTextures(void)
324 data[0] = 128; // normal X
325 data[1] = 128; // normal Y
326 data[2] = 255; // normal Z
327 data[3] = 128; // height
328 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
333 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
338 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
341 static void R_BuildNoTexture(void)
344 qbyte pix[16][16][4];
345 // this makes a light grey/dark grey checkerboard texture
346 for (y = 0;y < 16;y++)
348 for (x = 0;x < 16;x++)
350 if ((y < 8) ^ (x < 8))
366 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
369 static void R_BuildWhiteCube(void)
372 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
373 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
374 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
375 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
376 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
377 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
378 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
381 static void R_BuildNormalizationCube(void)
385 vec_t s, t, intensity;
387 qbyte data[6][NORMSIZE][NORMSIZE][4];
388 for (side = 0;side < 6;side++)
390 for (y = 0;y < NORMSIZE;y++)
392 for (x = 0;x < NORMSIZE;x++)
394 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
395 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
429 intensity = 127.0f / sqrt(DotProduct(v, v));
430 data[side][y][x][0] = 128.0f + intensity * v[0];
431 data[side][y][x][1] = 128.0f + intensity * v[1];
432 data[side][y][x][2] = 128.0f + intensity * v[2];
433 data[side][y][x][3] = 255;
437 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
440 void gl_main_start(void)
442 r_main_texturepool = R_AllocTexturePool();
443 r_bloom_texture_screen = NULL;
444 r_bloom_texture_bloom = NULL;
445 R_BuildBlankTextures();
447 R_BuildDetailTextures();
448 R_BuildDistortTexture();
449 if (gl_texturecubemap)
452 R_BuildNormalizationCube();
456 void gl_main_shutdown(void)
458 R_FreeTexturePool(&r_main_texturepool);
459 r_bloom_texture_screen = NULL;
460 r_bloom_texture_bloom = NULL;
461 r_texture_blanknormalmap = NULL;
462 r_texture_white = NULL;
463 r_texture_black = NULL;
464 r_texture_whitecube = NULL;
465 r_texture_normalizationcube = NULL;
468 extern void CL_ParseEntityLump(char *entitystring);
469 void gl_main_newmap(void)
471 // FIXME: move this code to client
473 char *entities, entname[MAX_QPATH];
477 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
478 l = (int)strlen(entname) - 4;
479 if (l >= 0 && !strcmp(entname + l, ".bsp"))
481 strcpy(entname + l, ".ent");
482 if ((entities = FS_LoadFile(entname, tempmempool, true)))
484 CL_ParseEntityLump(entities);
489 if (cl.worldmodel->brush.entities)
490 CL_ParseEntityLump(cl.worldmodel->brush.entities);
494 void GL_Main_Init(void)
496 Matrix4x4_CreateIdentity(&r_identitymatrix);
497 // FIXME: move this to client?
499 Cvar_RegisterVariable(&r_showtris);
500 Cvar_RegisterVariable(&r_drawentities);
501 Cvar_RegisterVariable(&r_drawviewmodel);
502 Cvar_RegisterVariable(&r_speeds);
503 Cvar_RegisterVariable(&r_fullbrights);
504 Cvar_RegisterVariable(&r_wateralpha);
505 Cvar_RegisterVariable(&r_dynamic);
506 Cvar_RegisterVariable(&r_fullbright);
507 Cvar_RegisterVariable(&r_textureunits);
508 Cvar_RegisterVariable(&r_lerpsprites);
509 Cvar_RegisterVariable(&r_lerpmodels);
510 Cvar_RegisterVariable(&r_waterscroll);
511 Cvar_RegisterVariable(&r_watershader);
512 Cvar_RegisterVariable(&r_drawcollisionbrushes);
513 Cvar_RegisterVariable(&r_bloom);
514 Cvar_RegisterVariable(&r_bloom_intensity);
515 Cvar_RegisterVariable(&r_bloom_blur);
516 Cvar_RegisterVariable(&r_bloom_resolution);
517 Cvar_RegisterVariable(&r_bloom_power);
518 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
519 Cvar_RegisterVariable(&developer_texturelogging);
520 Cvar_RegisterVariable(&gl_lightmaps);
521 if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
522 Cvar_SetValue("r_fullbrights", 0);
523 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
526 static vec3_t r_farclip_origin;
527 static vec3_t r_farclip_direction;
528 static vec_t r_farclip_directiondist;
529 static vec_t r_farclip_meshfarclip;
530 static int r_farclip_directionbit0;
531 static int r_farclip_directionbit1;
532 static int r_farclip_directionbit2;
534 // enlarge farclip to accomodate box
535 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
538 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
539 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
540 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
541 if (r_farclip_meshfarclip < d)
542 r_farclip_meshfarclip = d;
545 // return farclip value
546 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
550 VectorCopy(origin, r_farclip_origin);
551 VectorCopy(direction, r_farclip_direction);
552 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
553 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
554 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
555 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
556 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
558 if (r_refdef.worldmodel)
559 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
560 for (i = 0;i < r_refdef.numentities;i++)
561 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
563 return r_farclip_meshfarclip - r_farclip_directiondist;
566 extern void R_Textures_Init(void);
567 extern void GL_Draw_Init(void);
568 extern void GL_Main_Init(void);
569 extern void R_Shadow_Init(void);
570 extern void R_Sky_Init(void);
571 extern void GL_Surf_Init(void);
572 extern void R_Crosshairs_Init(void);
573 extern void R_Light_Init(void);
574 extern void R_Particles_Init(void);
575 extern void R_Explosion_Init(void);
576 extern void gl_backend_init(void);
577 extern void Sbar_Init(void);
578 extern void R_LightningBeams_Init(void);
579 extern void Mod_RenderInit(void);
581 void Render_Init(void)
597 R_LightningBeams_Init();
606 extern char *ENGINE_EXTENSIONS;
609 VID_CheckExtensions();
611 // LordHavoc: report supported extensions
612 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
614 // clear to black (loading plaque will be seen over this)
615 qglClearColor(0,0,0,1);
616 qglClear(GL_COLOR_BUFFER_BIT);
619 int R_CullBox(const vec3_t mins, const vec3_t maxs)
623 for (i = 0;i < 4;i++)
630 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
634 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
638 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
642 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
646 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
650 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
654 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
658 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
666 //==================================================================================
668 static void R_MarkEntities (void)
671 entity_render_t *ent;
673 if (!r_drawentities.integer)
676 r_refdef.worldentity->visframe = r_framecount;
677 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
678 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
680 // worldmodel can check visibility
681 for (i = 0;i < r_refdef.numentities;i++)
683 ent = r_refdef.entities[i];
684 Mod_CheckLoaded(ent->model);
685 // some of the renderer still relies on origin...
686 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
687 // some of the renderer still relies on scale...
688 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
689 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)))
691 R_UpdateEntLights(ent);
692 ent->visframe = r_framecount;
698 // no worldmodel or it can't check visibility
699 for (i = 0;i < r_refdef.numentities;i++)
701 ent = r_refdef.entities[i];
702 Mod_CheckLoaded(ent->model);
703 // some of the renderer still relies on origin...
704 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
705 // some of the renderer still relies on scale...
706 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
707 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
709 R_UpdateEntLights(ent);
710 ent->visframe = r_framecount;
716 // only used if skyrendermasked, and normally returns false
717 int R_DrawBrushModelsSky (void)
720 entity_render_t *ent;
722 if (!r_drawentities.integer)
726 for (i = 0;i < r_refdef.numentities;i++)
728 ent = r_refdef.entities[i];
729 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
731 ent->model->DrawSky(ent);
738 void R_DrawNoModel(entity_render_t *ent);
739 void R_DrawModels(void)
742 entity_render_t *ent;
744 if (!r_drawentities.integer)
747 for (i = 0;i < r_refdef.numentities;i++)
749 ent = r_refdef.entities[i];
750 if (ent->visframe == r_framecount)
752 if (ent->model && ent->model->Draw != NULL)
753 ent->model->Draw(ent);
760 static void R_SetFrustum(void)
762 // break apart the view matrix into vectors for various purposes
763 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
764 VectorNegate(r_viewleft, r_viewright);
766 // LordHavoc: note to all quake engine coders, the special case for 90
767 // degrees assumed a square view (wrong), so I removed it, Quake2 has it
770 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
771 RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
772 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
773 PlaneClassify(&frustum[0]);
775 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
776 RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
777 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
778 PlaneClassify(&frustum[1]);
780 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
781 RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
782 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
783 PlaneClassify(&frustum[2]);
785 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
786 RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
787 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
788 PlaneClassify(&frustum[3]);
791 VectorCopy(r_viewforward, frustum[4].normal);
792 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
793 PlaneClassify(&frustum[4]);
796 static void R_BlendView(void)
800 if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
803 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
806 R_Mesh_Matrix(&r_identitymatrix);
807 // vertex coordinates for a quad that covers the screen exactly
808 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
809 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
810 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
811 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
812 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)
814 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
815 float xoffset, yoffset, r;
817 // set the (poorly named) screenwidth and screenheight variables to
818 // a power of 2 at least as large as the screen, these will define the
819 // size of the texture to allocate
820 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
821 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
822 // allocate textures as needed
823 if (!r_bloom_texture_screen)
824 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
825 if (!r_bloom_texture_bloom)
826 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
827 // set bloomwidth and bloomheight to the bloom resolution that will be
828 // used (often less than the screen resolution for faster rendering)
829 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
830 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
831 // set up a texcoord array for the full resolution screen image
832 // (we have to keep this around to copy back during final render)
833 varray_texcoord2f[0][0] = 0;
834 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
835 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
836 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
837 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
838 varray_texcoord2f[0][5] = 0;
839 varray_texcoord2f[0][6] = 0;
840 varray_texcoord2f[0][7] = 0;
841 // set up a texcoord array for the reduced resolution bloom image
842 // (which will be additive blended over the screen image)
843 varray_texcoord2f[1][0] = 0;
844 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
845 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
846 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
847 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
848 varray_texcoord2f[1][5] = 0;
849 varray_texcoord2f[1][6] = 0;
850 varray_texcoord2f[1][7] = 0;
851 memset(&m, 0, sizeof(m));
852 m.pointer_vertex = varray_vertex3f;
853 m.pointer_texcoord[0] = varray_texcoord2f[0];
854 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
856 // copy view into the full resolution screen image texture
858 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
860 c_bloomcopypixels += r_view_width * r_view_height;
861 // now scale it down to the bloom size and raise to a power of itself
862 // to darken it (this leaves the really bright stuff bright, and
863 // everything else becomes very dark)
864 // TODO: optimize with multitexture or GLSL
865 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
866 GL_BlendFunc(GL_ONE, GL_ZERO);
867 GL_Color(1, 1, 1, 1);
868 R_Mesh_Draw(0, 4, 2, polygonelements);
870 c_bloomdrawpixels += bloomwidth * bloomheight;
871 // render multiple times with a multiply blendfunc to raise to a power
872 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
873 for (x = 1;x < r_bloom_power.integer;x++)
875 R_Mesh_Draw(0, 4, 2, polygonelements);
877 c_bloomdrawpixels += bloomwidth * bloomheight;
879 // we now have a darkened bloom image in the framebuffer, copy it into
880 // the bloom image texture for more processing
881 memset(&m, 0, sizeof(m));
882 m.pointer_vertex = varray_vertex3f;
883 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
884 m.pointer_texcoord[0] = varray_texcoord2f[2];
887 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
889 c_bloomcopypixels += bloomwidth * bloomheight;
890 // blend on at multiple vertical offsets to achieve a vertical blur
891 // TODO: do offset blends using GLSL
892 range = r_bloom_blur.integer * bloomwidth / 320;
893 GL_BlendFunc(GL_ONE, GL_ZERO);
894 for (x = -range;x <= range;x++)
896 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
897 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
898 // compute a texcoord array with the specified x and y offset
899 varray_texcoord2f[2][0] = xoffset+0;
900 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
901 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
902 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
903 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
904 varray_texcoord2f[2][5] = yoffset+0;
905 varray_texcoord2f[2][6] = xoffset+0;
906 varray_texcoord2f[2][7] = yoffset+0;
907 // this r value looks like a 'dot' particle, fading sharply to
908 // black at the edges
909 // (probably not realistic but looks good enough)
910 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
913 GL_Color(r, r, r, 1);
914 R_Mesh_Draw(0, 4, 2, polygonelements);
916 c_bloomdrawpixels += bloomwidth * bloomheight;
917 GL_BlendFunc(GL_ONE, GL_ONE);
919 // copy the vertically blurred bloom view to a texture
921 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
923 c_bloomcopypixels += bloomwidth * bloomheight;
924 // blend the vertically blurred image at multiple offsets horizontally
925 // to finish the blur effect
926 // TODO: do offset blends using GLSL
927 range = r_bloom_blur.integer * bloomwidth / 320;
928 GL_BlendFunc(GL_ONE, GL_ZERO);
929 for (x = -range;x <= range;x++)
931 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
932 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
933 // compute a texcoord array with the specified x and y offset
934 varray_texcoord2f[2][0] = xoffset+0;
935 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
936 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
937 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
938 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
939 varray_texcoord2f[2][5] = yoffset+0;
940 varray_texcoord2f[2][6] = xoffset+0;
941 varray_texcoord2f[2][7] = yoffset+0;
942 // this r value looks like a 'dot' particle, fading sharply to
943 // black at the edges
944 // (probably not realistic but looks good enough)
945 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
948 GL_Color(r, r, r, 1);
949 R_Mesh_Draw(0, 4, 2, polygonelements);
951 c_bloomdrawpixels += bloomwidth * bloomheight;
952 GL_BlendFunc(GL_ONE, GL_ONE);
954 // copy the blurred bloom view to a texture
956 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
958 c_bloomcopypixels += bloomwidth * bloomheight;
959 // go back to full view area
960 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
961 // put the original screen image back in place and blend the bloom
963 memset(&m, 0, sizeof(m));
964 m.pointer_vertex = varray_vertex3f;
965 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
966 m.pointer_texcoord[0] = varray_texcoord2f[0];
968 dobloomblend = false;
970 // do both in one pass if possible
971 if (r_textureunits.integer >= 2 && gl_combine.integer)
973 dobloomblend = false;
974 m.texcombinergb[1] = GL_ADD;
975 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
976 m.pointer_texcoord[1] = varray_texcoord2f[1];
982 GL_BlendFunc(GL_ONE, GL_ZERO);
984 R_Mesh_Draw(0, 4, 2, polygonelements);
986 c_bloomdrawpixels += r_view_width * r_view_height;
987 // now blend on the bloom texture if multipass
990 memset(&m, 0, sizeof(m));
991 m.pointer_vertex = varray_vertex3f;
992 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
993 m.pointer_texcoord[0] = varray_texcoord2f[1];
995 GL_BlendFunc(GL_ONE, GL_ONE);
997 R_Mesh_Draw(0, 4, 2, polygonelements);
999 c_bloomdrawpixels += r_view_width * r_view_height;
1002 if (r_refdef.viewblend[3] >= 0.01f)
1004 // apply a color tint to the whole view
1005 memset(&m, 0, sizeof(m));
1006 m.pointer_vertex = varray_vertex3f;
1008 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1009 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1010 R_Mesh_Draw(0, 4, 2, polygonelements);
1014 void R_RenderScene(void);
1016 matrix4x4_t r_waterscrollmatrix;
1023 void R_RenderView(void)
1025 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1026 return; //Host_Error ("R_RenderView: NULL worldmodel");
1028 r_view_width = bound(0, r_refdef.width, vid.width);
1029 r_view_height = bound(0, r_refdef.height, vid.height);
1031 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1032 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1034 r_view_fov_x = bound(1, r_refdef.fov_x, 170);
1035 r_view_fov_y = bound(1, r_refdef.fov_y, 170);
1036 r_view_matrix = r_refdef.viewentitymatrix;
1037 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1038 r_rtworld = r_shadow_realtime_world.integer;
1039 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1040 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1041 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1042 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1044 // GL is weird because it's bottom to top, r_view_y is top to bottom
1045 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1046 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1047 GL_ScissorTest(true);
1053 R_TimeReport("setup");
1055 qglDepthFunc(GL_LEQUAL);
1056 qglPolygonOffset(0, 0);
1057 qglEnable(GL_POLYGON_OFFSET_FILL);
1061 qglPolygonOffset(0, 0);
1062 qglDisable(GL_POLYGON_OFFSET_FILL);
1065 R_TimeReport("blendview");
1067 GL_Scissor(0, 0, vid.width, vid.height);
1068 GL_ScissorTest(false);
1071 extern void R_DrawLightningBeams (void);
1072 void R_RenderScene(void)
1074 // don't let sound skip if going slow
1075 if (r_refdef.extraupdate)
1080 R_MeshQueue_BeginScene();
1082 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1086 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1087 if (r_rtworldshadows || r_rtdlightshadows)
1088 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
1090 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
1092 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1094 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);
1098 R_WorldVisibility();
1099 R_TimeReport("worldvis");
1102 R_TimeReport("markentity");
1104 R_Shadow_UpdateWorldLightSelection();
1106 // don't let sound skip if going slow
1107 if (r_refdef.extraupdate)
1110 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1111 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1113 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1114 R_TimeReport("worldsky");
1117 if (R_DrawBrushModelsSky())
1118 R_TimeReport("bmodelsky");
1120 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1121 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1123 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1124 R_TimeReport("world");
1127 // don't let sound skip if going slow
1128 if (r_refdef.extraupdate)
1131 GL_ShowTrisColor(0, 0.015, 0, 1);
1134 R_TimeReport("models");
1136 // don't let sound skip if going slow
1137 if (r_refdef.extraupdate)
1140 GL_ShowTrisColor(0, 0, 0.033, 1);
1141 R_ShadowVolumeLighting(false);
1142 R_TimeReport("rtlights");
1144 // don't let sound skip if going slow
1145 if (r_refdef.extraupdate)
1148 GL_ShowTrisColor(0.1, 0, 0, 1);
1150 R_DrawLightningBeams();
1151 R_TimeReport("lightning");
1154 R_TimeReport("particles");
1157 R_TimeReport("explosions");
1159 R_MeshQueue_RenderTransparent();
1160 R_TimeReport("drawtrans");
1163 R_TimeReport("coronas");
1165 R_DrawWorldCrosshair();
1166 R_TimeReport("crosshair");
1168 R_MeshQueue_Render();
1169 R_MeshQueue_EndScene();
1171 if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1173 R_ShadowVolumeLighting(true);
1174 R_TimeReport("visiblevolume");
1177 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1179 // don't let sound skip if going slow
1180 if (r_refdef.extraupdate)
1185 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1188 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1190 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1191 GL_DepthMask(false);
1193 R_Mesh_Matrix(&r_identitymatrix);
1195 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1196 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1197 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1198 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1199 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1200 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1201 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1202 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1203 R_FillColors(color, 8, cr, cg, cb, ca);
1206 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1208 VectorSubtract(v, r_vieworigin, diff);
1209 f2 = exp(fogdensity/DotProduct(diff, diff));
1211 c[0] = c[0] * f1 + fogcolor[0] * f2;
1212 c[1] = c[1] * f1 + fogcolor[1] * f2;
1213 c[2] = c[2] * f1 + fogcolor[2] * f2;
1216 memset(&m, 0, sizeof(m));
1217 m.pointer_vertex = vertex3f;
1218 m.pointer_color = color;
1224 int nomodelelements[24] =
1236 float nomodelvertex3f[6*3] =
1246 float nomodelcolor4f[6*4] =
1248 0.0f, 0.0f, 0.5f, 1.0f,
1249 0.0f, 0.0f, 0.5f, 1.0f,
1250 0.0f, 0.5f, 0.0f, 1.0f,
1251 0.0f, 0.5f, 0.0f, 1.0f,
1252 0.5f, 0.0f, 0.0f, 1.0f,
1253 0.5f, 0.0f, 0.0f, 1.0f
1256 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1258 const entity_render_t *ent = calldata1;
1260 float f1, f2, *c, diff[3];
1263 R_Mesh_Matrix(&ent->matrix);
1265 memset(&m, 0, sizeof(m));
1266 m.pointer_vertex = nomodelvertex3f;
1268 if (ent->flags & EF_ADDITIVE)
1270 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1271 GL_DepthMask(false);
1273 else if (ent->alpha < 1)
1275 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1276 GL_DepthMask(false);
1280 GL_BlendFunc(GL_ONE, GL_ZERO);
1283 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1286 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1287 m.pointer_color = color4f;
1288 VectorSubtract(ent->origin, r_vieworigin, diff);
1289 f2 = exp(fogdensity/DotProduct(diff, diff));
1291 for (i = 0, c = color4f;i < 6;i++, c += 4)
1293 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1294 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1295 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1299 else if (ent->alpha != 1)
1301 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1302 m.pointer_color = color4f;
1303 for (i = 0, c = color4f;i < 6;i++, c += 4)
1307 m.pointer_color = nomodelcolor4f;
1309 R_Mesh_Draw(0, 6, 8, nomodelelements);
1312 void R_DrawNoModel(entity_render_t *ent)
1314 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1315 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1317 // R_DrawNoModelCallback(ent, 0);
1320 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1322 vec3_t right1, right2, diff, normal;
1324 VectorSubtract (org2, org1, normal);
1326 // calculate 'right' vector for start
1327 VectorSubtract (r_vieworigin, org1, diff);
1328 CrossProduct (normal, diff, right1);
1329 VectorNormalize (right1);
1331 // calculate 'right' vector for end
1332 VectorSubtract (r_vieworigin, org2, diff);
1333 CrossProduct (normal, diff, right2);
1334 VectorNormalize (right2);
1336 vert[ 0] = org1[0] + width * right1[0];
1337 vert[ 1] = org1[1] + width * right1[1];
1338 vert[ 2] = org1[2] + width * right1[2];
1339 vert[ 3] = org1[0] - width * right1[0];
1340 vert[ 4] = org1[1] - width * right1[1];
1341 vert[ 5] = org1[2] - width * right1[2];
1342 vert[ 6] = org2[0] - width * right2[0];
1343 vert[ 7] = org2[1] - width * right2[1];
1344 vert[ 8] = org2[2] - width * right2[2];
1345 vert[ 9] = org2[0] + width * right2[0];
1346 vert[10] = org2[1] + width * right2[1];
1347 vert[11] = org2[2] + width * right2[2];
1350 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1352 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, int depthdisable, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca)
1359 VectorSubtract(origin, r_vieworigin, diff);
1360 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1363 R_Mesh_Matrix(&r_identitymatrix);
1364 GL_BlendFunc(blendfunc1, blendfunc2);
1365 GL_DepthMask(false);
1366 GL_DepthTest(!depthdisable);
1368 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1369 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1370 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1371 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1372 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1373 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1374 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1375 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1376 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1377 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1378 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1379 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1381 memset(&m, 0, sizeof(m));
1382 m.tex[0] = R_GetTexture(texture);
1383 m.pointer_texcoord[0] = spritetexcoord2f;
1384 m.pointer_vertex = varray_vertex3f;
1386 GL_Color(cr, cg, cb, ca);
1387 R_Mesh_Draw(0, 4, 2, polygonelements);
1390 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1394 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1395 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1397 if (i == mesh->numvertices)
1399 if (mesh->numvertices < mesh->maxvertices)
1401 VectorCopy(v, vertex3f);
1402 mesh->numvertices++;
1404 return mesh->numvertices;
1410 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1414 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1415 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1416 e = mesh->element3i + mesh->numtriangles * 3;
1417 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1419 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1420 if (mesh->numtriangles < mesh->maxtriangles)
1425 mesh->numtriangles++;
1427 element[1] = element[2];
1431 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1433 int planenum, planenum2;
1436 mplane_t *plane, *plane2;
1437 float temppoints[2][256*3];
1438 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1442 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1443 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1445 if (planenum2 == planenum)
1447 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);
1450 if (tempnumpoints < 3)
1452 // generate elements forming a triangle fan for this polygon
1453 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1457 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1459 texture_t *texture = t;
1460 model_t *model = ent->model;
1461 int s = ent->skinnum;
1462 if ((unsigned int)s >= (unsigned int)model->numskins)
1466 if (model->skinscenes)
1468 if (model->skinscenes[s].framecount > 1)
1469 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1471 s = model->skinscenes[s].firstframe;
1474 t = t + s * model->num_surfaces;
1476 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];
1477 texture->currentframe = t;
1478 t->currentmaterialflags = t->basematerialflags;
1479 t->currentalpha = ent->alpha;
1480 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1481 t->currentalpha *= r_wateralpha.value;
1482 if (!(ent->flags & RENDER_LIGHT))
1483 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1484 if (ent->effects & EF_ADDITIVE)
1485 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1486 else if (t->currentalpha < 1)
1487 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1488 if (ent->effects & EF_NODEPTHTEST)
1489 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1492 void R_UpdateAllTextureInfo(entity_render_t *ent)
1496 for (i = 0;i < ent->model->num_textures;i++)
1497 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1500 float *rsurface_vertex3f;
1501 float *rsurface_svector3f;
1502 float *rsurface_tvector3f;
1503 float *rsurface_normal3f;
1504 float *rsurface_lightmapcolor4f;
1506 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1509 float center[3], forward[3], right[3], up[3], v[4][3];
1510 matrix4x4_t matrix1, imatrix1;
1511 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1513 rsurface_vertex3f = varray_vertex3f;
1514 rsurface_svector3f = NULL;
1515 rsurface_tvector3f = NULL;
1516 rsurface_normal3f = NULL;
1517 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1521 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1522 rsurface_svector3f = surface->groupmesh->data_svector3f;
1523 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1524 rsurface_normal3f = surface->groupmesh->data_normal3f;
1526 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1528 if (!rsurface_svector3f)
1530 rsurface_svector3f = varray_svector3f;
1531 rsurface_tvector3f = varray_tvector3f;
1532 rsurface_normal3f = varray_normal3f;
1533 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);
1535 // a single autosprite surface can contain multiple sprites...
1536 VectorClear(forward);
1538 VectorSet(up, 0, 0, 1);
1539 for (j = 0;j < surface->num_vertices - 3;j += 4)
1541 VectorClear(center);
1542 for (i = 0;i < 4;i++)
1543 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1544 VectorScale(center, 0.25f, center);
1545 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1546 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);
1547 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1548 for (i = 0;i < 4;i++)
1549 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1550 forward[0] = modelorg[0] - center[0];
1551 forward[1] = modelorg[1] - center[1];
1552 VectorNormalize(forward);
1553 right[0] = forward[1];
1554 right[1] = -forward[0];
1555 for (i = 0;i < 4;i++)
1556 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1558 rsurface_vertex3f = varray_vertex3f;
1559 rsurface_svector3f = NULL;
1560 rsurface_tvector3f = NULL;
1561 rsurface_normal3f = NULL;
1563 else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1565 if (!rsurface_svector3f)
1567 rsurface_svector3f = varray_svector3f;
1568 rsurface_tvector3f = varray_tvector3f;
1569 rsurface_normal3f = varray_normal3f;
1570 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);
1572 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1573 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1574 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1575 // a single autosprite surface can contain multiple sprites...
1576 for (j = 0;j < surface->num_vertices - 3;j += 4)
1578 VectorClear(center);
1579 for (i = 0;i < 4;i++)
1580 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1581 VectorScale(center, 0.25f, center);
1582 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1583 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);
1584 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1585 for (i = 0;i < 4;i++)
1586 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1587 for (i = 0;i < 4;i++)
1588 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1590 rsurface_vertex3f = varray_vertex3f;
1591 rsurface_svector3f = NULL;
1592 rsurface_tvector3f = NULL;
1593 rsurface_normal3f = NULL;
1595 R_Mesh_VertexPointer(rsurface_vertex3f);
1598 void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, qboolean lightmodel, qboolean vertexlight, qboolean applycolor, qboolean applyfog)
1606 vec4_t ambientcolor4f;
1607 vec3_t diffusecolor;
1608 vec3_t diffusenormal;
1609 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r, g, b, a, false))
1611 rsurface_lightmapcolor4f = varray_color4f;
1612 if (rsurface_normal3f == NULL)
1614 rsurface_normal3f = varray_normal3f;
1615 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);
1617 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);
1626 r = ambientcolor4f[0];
1627 g = ambientcolor4f[1];
1628 b = ambientcolor4f[2];
1629 a = ambientcolor4f[3];
1630 rsurface_lightmapcolor4f = NULL;
1633 else if (vertexlight)
1635 if (surface->lightmapinfo)
1637 rsurface_lightmapcolor4f = varray_color4f;
1638 for (i = 0, c = rsurface_lightmapcolor4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1640 const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1641 float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1642 VectorScale(lm, scale, c);
1643 if (surface->lightmapinfo->styles[1] != 255)
1645 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1647 scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1648 VectorMA(c, scale, lm, c);
1649 if (surface->lightmapinfo->styles[2] != 255)
1652 scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1653 VectorMA(c, scale, lm, c);
1654 if (surface->lightmapinfo->styles[3] != 255)
1657 scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1658 VectorMA(c, scale, lm, c);
1665 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1668 rsurface_lightmapcolor4f = NULL;
1671 if (rsurface_lightmapcolor4f)
1673 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)
1675 VectorSubtract(v, modelorg, diff);
1676 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1685 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)
1687 VectorSubtract(v, modelorg, diff);
1688 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1695 rsurface_lightmapcolor4f = varray_color4f;
1697 if (applycolor && rsurface_lightmapcolor4f)
1699 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)
1707 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1708 GL_Color(r, g, b, a);
1712 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1715 int texturesurfaceindex;
1719 float colorpants[3], colorshirt[3];
1720 float f, r, g, b, a, colorscale;
1721 const msurface_t *surface;
1722 qboolean dolightmap;
1727 qboolean fogallpasses;
1728 qboolean waterscrolling;
1731 qboolean dofullbrightpants;
1732 qboolean dofullbrightshirt;
1733 qboolean applycolor;
1734 qboolean lightmodel = false;
1735 rtexture_t *basetexture;
1737 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1739 c_faces += texturenumsurfaces;
1740 // FIXME: identify models using a better check than ent->model->shadowmesh
1741 if (!(ent->effects & EF_FULLBRIGHT) && !ent->model->brush.shadowmesh)
1743 // gl_lightmaps debugging mode skips normal texturing
1744 if (gl_lightmaps.integer)
1746 GL_BlendFunc(GL_ONE, GL_ZERO);
1749 qglDisable(GL_CULL_FACE);
1750 GL_Color(1, 1, 1, 1);
1751 memset(&m, 0, sizeof(m));
1753 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1755 surface = texturesurfacelist[texturesurfaceindex];
1756 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1757 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1758 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1759 RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, lightmodel, !surface->lightmaptexture, false, false);
1760 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1761 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1762 GL_LockArrays(0, 0);
1764 qglEnable(GL_CULL_FACE);
1767 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1768 GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT));
1769 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
1770 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1771 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
1772 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1774 GL_BlendFunc(GL_ONE, GL_ZERO);
1775 // water waterscrolling in texture matrix
1776 waterscrolling = (texture->currentmaterialflags & MATERIALFLAG_WATER) && r_waterscroll.value != 0;
1777 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1778 qglDisable(GL_CULL_FACE);
1779 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
1783 skyrendernow = false;
1784 if (skyrendermasked)
1787 // LordHavoc: HalfLife maps have freaky skypolys...
1788 //if (!ent->model->brush.ishlbsp)
1790 R_Mesh_Matrix(&ent->matrix);
1791 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
1792 if (skyrendermasked)
1794 // depth-only (masking)
1795 GL_ColorMask(0,0,0,0);
1796 // just to make sure that braindead drivers don't draw anything
1797 // despite that colormask...
1798 GL_BlendFunc(GL_ZERO, GL_ONE);
1803 GL_BlendFunc(GL_ONE, GL_ZERO);
1807 memset(&m, 0, sizeof(m));
1809 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1811 surface = texturesurfacelist[texturesurfaceindex];
1812 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1813 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1814 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1815 GL_LockArrays(0, 0);
1817 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1820 else if ((texture->currentmaterialflags & MATERIALFLAG_WATER) && r_watershader.value && gl_textureshader && !texture->skin.glow && !fogenabled && ent->colormod[0] == 1 && ent->colormod[1] == 1 && ent->colormod[2] == 1)
1822 // NVIDIA Geforce3 distortion texture shader on water
1823 float args[4] = {0.05f,0,0,0.04f};
1824 memset(&m, 0, sizeof(m));
1825 m.tex[0] = R_GetTexture(r_texture_distorttexture[(int)(r_refdef.time * 16)&63]);
1826 m.tex[1] = R_GetTexture(texture->skin.base);
1827 m.texcombinergb[0] = GL_REPLACE;
1828 m.texcombinergb[1] = GL_REPLACE;
1829 Matrix4x4_CreateFromQuakeEntity(&m.texmatrix[0], 0, 0, 0, 0, 0, 0, r_watershader.value);
1830 m.texmatrix[1] = r_waterscrollmatrix;
1833 GL_Color(1, 1, 1, texture->currentalpha);
1834 GL_ActiveTexture(0);
1835 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1836 GL_ActiveTexture(1);
1837 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV);
1838 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB);
1839 qglTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, &args[0]);
1840 qglEnable(GL_TEXTURE_SHADER_NV);
1842 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1844 surface = texturesurfacelist[texturesurfaceindex];
1845 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1846 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1847 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1848 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1849 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1850 GL_LockArrays(0, 0);
1853 qglDisable(GL_TEXTURE_SHADER_NV);
1854 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1855 GL_ActiveTexture(0);
1857 else if (texture->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1859 // normal surface (wall or water)
1860 dolightmap = !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT);
1861 doambient = r_ambient.value >= (1/64.0f);
1862 dodetail = r_detailtextures.integer && texture->skin.detail != NULL && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
1863 doglow = texture->skin.glow != NULL;
1864 dofogpass = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD);
1865 fogallpasses = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
1866 if (ent->colormap >= 0)
1870 basetexture = texture->skin.base;
1871 dopants = texture->skin.pants != NULL;
1872 doshirt = texture->skin.shirt != NULL;
1873 // 128-224 are backwards ranges
1874 b = (ent->colormap & 0xF) << 4;b += (b >= 128 && b < 224) ? 4 : 12;
1875 dofullbrightpants = b >= 224;
1876 bcolor = (qbyte *) (&palette_complete[b]);
1877 VectorScale(bcolor, (1.0f / 255.0f), colorpants);
1878 // 128-224 are backwards ranges
1879 b = (ent->colormap & 0xF0);b += (b >= 128 && b < 224) ? 4 : 12;
1880 dofullbrightshirt = b >= 224;
1881 bcolor = (qbyte *) (&palette_complete[b]);
1882 VectorScale(bcolor, (1.0f / 255.0f), colorshirt);
1886 basetexture = texture->skin.merged ? texture->skin.merged : texture->skin.base;
1889 dofullbrightshirt = false;
1890 dofullbrightpants = false;
1892 if (dolightmap && r_textureunits.integer >= 2 && gl_combine.integer)
1894 memset(&m, 0, sizeof(m));
1895 m.tex[1] = R_GetTexture(basetexture);
1897 m.texmatrix[1] = r_waterscrollmatrix;
1898 m.texrgbscale[1] = 2;
1899 m.pointer_color = varray_color4f;
1901 // transparent is not affected by r_lightmapintensity
1902 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1903 colorscale = r_lightmapintensity;
1906 r = ent->colormod[0] * colorscale;
1907 g = ent->colormod[1] * colorscale;
1908 b = ent->colormod[2] * colorscale;
1909 a = texture->currentalpha;
1910 // q3bsp has no lightmap updates, so the lightstylevalue that
1911 // would normally be baked into the lightmaptexture must be
1912 // applied to the color
1913 if (ent->model->brushq3.data_lightmaps)
1915 float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
1920 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
1921 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1923 surface = texturesurfacelist[texturesurfaceindex];
1924 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1925 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1926 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1927 if (surface->lightmaptexture)
1928 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1930 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1931 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmodel, !surface->lightmaptexture, applycolor, fogallpasses);
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);
1937 else if (dolightmap && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT) && !lightmodel)
1940 GL_BlendFunc(GL_ONE, GL_ZERO);
1942 GL_Color(1, 1, 1, 1);
1943 memset(&m, 0, sizeof(m));
1945 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1947 surface = texturesurfacelist[texturesurfaceindex];
1948 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1949 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1950 if (surface->lightmaptexture)
1952 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1953 R_Mesh_ColorPointer(NULL);
1957 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1958 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
1960 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1961 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1962 GL_LockArrays(0, 0);
1964 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1965 GL_DepthMask(false);
1966 GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
1967 memset(&m, 0, sizeof(m));
1968 m.tex[0] = R_GetTexture(basetexture);
1970 m.texmatrix[0] = r_waterscrollmatrix;
1972 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1974 surface = texturesurfacelist[texturesurfaceindex];
1975 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1976 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1977 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1978 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1979 GL_LockArrays(0, 0);
1984 memset(&m, 0, sizeof(m));
1985 m.tex[0] = R_GetTexture(basetexture);
1987 m.texmatrix[0] = r_waterscrollmatrix;
1988 m.pointer_color = varray_color4f;
1990 if (gl_combine.integer)
1992 m.texrgbscale[0] = 2;
1995 // transparent is not affected by r_lightmapintensity
1996 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1997 colorscale *= r_lightmapintensity;
1999 r = ent->colormod[0] * colorscale;
2000 g = ent->colormod[1] * colorscale;
2001 b = ent->colormod[2] * colorscale;
2002 a = texture->currentalpha;
2005 // q3bsp has no lightmap updates, so the lightstylevalue that
2006 // would normally be baked into the lightmaptexture must be
2007 // applied to the color
2008 if (ent->model->brushq3.data_lightmaps)
2010 float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
2015 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2016 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2018 surface = texturesurfacelist[texturesurfaceindex];
2019 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2020 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2021 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmodel, true, applycolor, fogallpasses);
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);
2029 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2030 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2032 surface = texturesurfacelist[texturesurfaceindex];
2033 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2034 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2035 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, false, false, applycolor, fogallpasses);
2036 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2037 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2038 GL_LockArrays(0, 0);
2044 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2045 memset(&m, 0, sizeof(m));
2046 m.tex[0] = R_GetTexture(texture->skin.pants);
2048 m.texmatrix[0] = r_waterscrollmatrix;
2049 m.pointer_color = varray_color4f;
2051 if (gl_combine.integer)
2053 m.texrgbscale[0] = 2;
2056 // transparent is not affected by r_lightmapintensity
2057 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2058 colorscale *= r_lightmapintensity;
2060 r = ent->colormod[0] * colorpants[0] * colorscale;
2061 g = ent->colormod[1] * colorpants[1] * colorscale;
2062 b = ent->colormod[2] * colorpants[2] * colorscale;
2063 a = texture->currentalpha;
2064 if (dolightmap && !dofullbrightpants)
2066 // q3bsp has no lightmap updates, so the lightstylevalue that
2067 // would normally be baked into the lightmaptexture must be
2068 // applied to the color
2069 if (ent->model->brushq3.data_lightmaps)
2071 float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
2076 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2077 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2079 surface = texturesurfacelist[texturesurfaceindex];
2080 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2081 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2082 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmodel, true, applycolor, fogallpasses);
2083 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2084 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2085 GL_LockArrays(0, 0);
2090 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2091 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2093 surface = texturesurfacelist[texturesurfaceindex];
2094 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2095 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2096 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, false, false, applycolor, fogallpasses);
2097 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2098 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2099 GL_LockArrays(0, 0);
2105 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2106 memset(&m, 0, sizeof(m));
2107 m.tex[0] = R_GetTexture(texture->skin.shirt);
2109 m.texmatrix[0] = r_waterscrollmatrix;
2110 m.pointer_color = varray_color4f;
2112 if (gl_combine.integer)
2114 m.texrgbscale[0] = 2;
2117 // transparent is not affected by r_lightmapintensity
2118 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2119 colorscale *= r_lightmapintensity;
2121 r = ent->colormod[0] * colorshirt[0] * colorscale;
2122 g = ent->colormod[1] * colorshirt[1] * colorscale;
2123 b = ent->colormod[2] * colorshirt[2] * colorscale;
2124 a = texture->currentalpha;
2125 if (dolightmap && !dofullbrightshirt)
2127 // q3bsp has no lightmap updates, so the lightstylevalue that
2128 // would normally be baked into the lightmaptexture must be
2129 // applied to the color
2130 if (ent->model->brushq3.data_lightmaps)
2132 float scale = d_lightstylevalue[0] * (1.0f / 128.0f);
2137 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2138 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2140 surface = texturesurfacelist[texturesurfaceindex];
2141 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2142 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2143 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmodel, true, applycolor, fogallpasses);
2144 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2145 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2146 GL_LockArrays(0, 0);
2151 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2152 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2154 surface = texturesurfacelist[texturesurfaceindex];
2155 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2156 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2157 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, false, false, applycolor, fogallpasses);
2158 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2159 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2160 GL_LockArrays(0, 0);
2167 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2168 GL_DepthMask(false);
2169 memset(&m, 0, sizeof(m));
2170 m.tex[0] = R_GetTexture(texture->skin.base);
2172 m.texmatrix[0] = r_waterscrollmatrix;
2173 m.pointer_color = varray_color4f;
2175 if (gl_combine.integer)
2177 m.texrgbscale[0] = 2;
2181 colorscale *= r_ambient.value * (1.0f / 64.0f);
2182 r = ent->colormod[0] * colorscale;
2183 g = ent->colormod[1] * colorscale;
2184 b = ent->colormod[2] * colorscale;
2185 a = texture->currentalpha;
2186 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2187 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2189 surface = texturesurfacelist[texturesurfaceindex];
2190 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2191 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2192 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, false, false, applycolor, fogallpasses);
2193 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2194 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2195 GL_LockArrays(0, 0);
2200 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2201 GL_DepthMask(false);
2202 GL_Color(1, 1, 1, 1);
2203 memset(&m, 0, sizeof(m));
2204 m.tex[0] = R_GetTexture(texture->skin.detail);
2206 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2208 surface = texturesurfacelist[texturesurfaceindex];
2209 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2210 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoorddetail2f);
2211 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2212 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2213 GL_LockArrays(0, 0);
2218 // if glow was not already done using multitexture, do it now.
2219 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2220 GL_DepthMask(false);
2221 memset(&m, 0, sizeof(m));
2222 m.tex[0] = R_GetTexture(texture->skin.glow);
2224 m.texmatrix[0] = r_waterscrollmatrix;
2225 m.pointer_color = varray_color4f;
2228 r = ent->colormod[0] * colorscale;
2229 g = ent->colormod[1] * colorscale;
2230 b = ent->colormod[2] * colorscale;
2231 a = texture->currentalpha;
2232 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2233 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2235 surface = texturesurfacelist[texturesurfaceindex];
2236 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2237 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2238 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, false, false, applycolor, fogallpasses);
2239 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2240 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2241 GL_LockArrays(0, 0);
2246 // if this is opaque use alpha blend which will darken the earlier
2249 // if this is an alpha blended material, all the earlier passes
2250 // were darkened by fog already, so we only need to add the fog
2251 // color ontop through the fog mask texture
2253 // if this is an additive blended material, all the earlier passes
2254 // were darkened by fog already, and we should not add fog color
2255 // (because the background was not darkened, there is no fog color
2256 // that was lost behind it).
2258 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2260 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2261 GL_DepthMask(false);
2262 memset(&m, 0, sizeof(m));
2263 m.tex[0] = R_GetTexture(texture->skin.fog);
2265 m.texmatrix[0] = r_waterscrollmatrix;
2270 a = texture->currentalpha;
2271 applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2272 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2274 surface = texturesurfacelist[texturesurfaceindex];
2275 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2276 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2277 R_Mesh_ColorPointer(varray_color4f);
2278 //RSurf_FogPassColors_Vertex3f_Color4f((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], texture->currentalpha, 1, surface->num_vertices, modelorg);
2279 if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2281 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)
2283 VectorSubtract(v, modelorg, diff);
2284 f = exp(fogdensity/DotProduct(diff, diff));
2288 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * f * a;
2293 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)
2295 VectorSubtract(v, modelorg, diff);
2296 f = exp(fogdensity/DotProduct(diff, diff));
2303 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2304 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2305 GL_LockArrays(0, 0);
2309 if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2310 qglEnable(GL_CULL_FACE);
2313 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2315 const entity_render_t *ent = calldata1;
2316 const msurface_t *surface = ent->model->data_surfaces + calldata2;
2320 texture = surface->texture;
2321 if (texture->basematerialflags & MATERIALFLAG_SKY)
2322 return; // transparent sky is too difficult
2323 R_UpdateTextureInfo(ent, texture);
2325 R_Mesh_Matrix(&ent->matrix);
2326 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2327 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2330 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2332 int texturesurfaceindex;
2333 const msurface_t *surface;
2334 vec3_t tempcenter, center;
2335 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2337 // drawing sky transparently would be too difficult
2338 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2340 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2342 surface = texturesurfacelist[texturesurfaceindex];
2343 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2344 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2345 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2346 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2347 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2352 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2355 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2356 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2358 int i, j, f, flagsmask;
2359 msurface_t *surface, **surfacechain;
2360 texture_t *t, *texture;
2361 model_t *model = ent->model;
2363 const int maxsurfacelist = 1024;
2364 int numsurfacelist = 0;
2365 const msurface_t *surfacelist[1024];
2368 R_Mesh_Matrix(&ent->matrix);
2369 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2371 // update light styles
2372 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2374 for (i = 0;i < model->brushq1.light_styles;i++)
2376 if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
2378 model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
2379 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2380 for (;(surface = *surfacechain);surfacechain++)
2381 surface->cached_dlight = true;
2386 R_UpdateAllTextureInfo(ent);
2387 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2392 if (ent == r_refdef.worldentity)
2394 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2396 if (!r_worldsurfacevisible[j])
2398 if (t != surface->texture)
2402 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2405 t = surface->texture;
2406 texture = t->currentframe;
2407 f = texture->currentmaterialflags & flagsmask;
2409 if (f && surface->num_triangles)
2411 // if lightmap parameters changed, rebuild lightmap texture
2412 if (surface->cached_dlight && surface->lightmapinfo->samples)
2413 R_BuildLightMap(ent, surface);
2414 // add face to draw list
2415 surfacelist[numsurfacelist++] = surface;
2416 if (numsurfacelist >= maxsurfacelist)
2418 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2426 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2428 if (t != surface->texture)
2432 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2435 t = surface->texture;
2436 texture = t->currentframe;
2437 f = texture->currentmaterialflags & flagsmask;
2439 if (f && surface->num_triangles)
2441 // if lightmap parameters changed, rebuild lightmap texture
2442 if (surface->cached_dlight && surface->lightmapinfo->samples)
2443 R_BuildLightMap(ent, surface);
2444 // add face to draw list
2445 surfacelist[numsurfacelist++] = surface;
2446 if (numsurfacelist >= maxsurfacelist)
2448 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2455 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);