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 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
29 // used for dlight push checking and other things
34 renderstats_t renderstats;
36 // true during envmap command capture
39 // maximum visible distance (recalculated from world box each frame)
41 // brightness of world lightmaps and related lighting
42 // (often reduced when world rtlights are enabled)
43 float r_lightmapintensity;
44 // whether to draw world lights realtime, dlights realtime, and their shadows
46 qboolean r_rtworldshadows;
48 qboolean r_rtdlightshadows;
51 // forces all rendering to draw triangle outlines
66 matrix4x4_t r_view_matrix;
73 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_showtris_polygonoffset = {0, "r_showtris_polygonoffset", "-10", "nudges triangle outlines in hardware depth units, used to make outlines appear infront of walls"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing\n"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
85 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
86 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
87 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
88 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
89 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
91 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
92 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
93 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
94 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
95 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
96 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
97 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
99 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
101 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
102 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "enables offset mapping effect (also known as parallax mapping or sometimes as virtual displacement mapping, not as good as relief mapping or silohuette mapping but much faster), can cause strange artifacts on many textures, requires bumpmaps for depth information (normalmaps can have depth information as alpha channel, but most do not)"};
103 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "-0.04", "how deep the offset mapping effect is, and whether it is inward or outward"};
104 cvar_t r_glsl_offsetmapping_bias = {0, "r_glsl_offsetmapping_bias", "0.04", "pushes the effect closer/further"};
105 cvar_t r_glsl_usehalffloat = {0, "r_glsl_usehalffloat", "0", "use half and hvec variables in GLSL shader for a speed gain (NVIDIA only)"};
106 cvar_t r_glsl_surfacenormalize = {0, "r_glsl_surfacenormalize", "1", "normalize bumpmap texels in GLSL shader, produces a more rounded look on small bumps and dents"};
107 cvar_t r_glsl_deluxemapping = {0, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
109 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
110 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
111 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
113 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
114 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
115 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
116 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
117 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
119 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
121 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
123 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
125 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
127 rtexture_t *r_bloom_texture_screen;
128 rtexture_t *r_bloom_texture_bloom;
129 rtexture_t *r_texture_blanknormalmap;
130 rtexture_t *r_texture_white;
131 rtexture_t *r_texture_black;
132 rtexture_t *r_texture_notexture;
133 rtexture_t *r_texture_whitecube;
134 rtexture_t *r_texture_normalizationcube;
135 rtexture_t *r_texture_fogattenuation;
136 rtexture_t *r_texture_fogintensity;
138 // information about each possible shader permutation
139 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
140 // currently selected permutation
141 r_glsl_permutation_t *r_glsl_permutation;
143 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
146 for (i = 0;i < verts;i++)
157 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
160 for (i = 0;i < verts;i++)
175 vec_t fogtabledistmultiplier;
176 float fogtable[FOGTABLEWIDTH];
177 float fog_density, fog_red, fog_green, fog_blue;
179 qboolean oldgl_fogenable;
180 void R_UpdateFog(void)
182 if (gamemode == GAME_NEHAHRA)
184 if (gl_fogenable.integer)
186 oldgl_fogenable = true;
187 fog_density = gl_fogdensity.value;
188 fog_red = gl_fogred.value;
189 fog_green = gl_foggreen.value;
190 fog_blue = gl_fogblue.value;
192 else if (oldgl_fogenable)
194 oldgl_fogenable = false;
203 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
204 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
205 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
210 fogdensity = -4000.0f / (fog_density * fog_density);
211 // this is the point where the fog reaches 0.9986 alpha, which we
212 // consider a good enough cutoff point for the texture
213 // (0.9986 * 256 == 255.6)
214 fogrange = 400 / fog_density;
215 fograngerecip = 1.0f / fogrange;
216 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
217 // fog color was already set
223 // FIXME: move this to client?
226 if (gamemode == GAME_NEHAHRA)
228 Cvar_Set("gl_fogenable", "0");
229 Cvar_Set("gl_fogdensity", "0.2");
230 Cvar_Set("gl_fogred", "0.3");
231 Cvar_Set("gl_foggreen", "0.3");
232 Cvar_Set("gl_fogblue", "0.3");
234 fog_density = fog_red = fog_green = fog_blue = 0.0f;
237 // FIXME: move this to client?
238 void FOG_registercvars(void)
243 if (gamemode == GAME_NEHAHRA)
245 Cvar_RegisterVariable (&gl_fogenable);
246 Cvar_RegisterVariable (&gl_fogdensity);
247 Cvar_RegisterVariable (&gl_fogred);
248 Cvar_RegisterVariable (&gl_foggreen);
249 Cvar_RegisterVariable (&gl_fogblue);
250 Cvar_RegisterVariable (&gl_fogstart);
251 Cvar_RegisterVariable (&gl_fogend);
254 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
255 for (x = 0;x < FOGTABLEWIDTH;x++)
257 alpha = exp(r / ((double)x*(double)x));
258 if (x == FOGTABLEWIDTH - 1)
260 fogtable[x] = bound(0, alpha, 1);
264 static void R_BuildBlankTextures(void)
266 unsigned char data[4];
267 data[0] = 128; // normal X
268 data[1] = 128; // normal Y
269 data[2] = 255; // normal Z
270 data[3] = 128; // height
271 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
276 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
281 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
284 static void R_BuildNoTexture(void)
287 unsigned char pix[16][16][4];
288 // this makes a light grey/dark grey checkerboard texture
289 for (y = 0;y < 16;y++)
291 for (x = 0;x < 16;x++)
293 if ((y < 8) ^ (x < 8))
309 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
312 static void R_BuildWhiteCube(void)
314 unsigned char data[6*1*1*4];
315 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
316 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
317 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
318 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
319 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
320 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
321 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
324 static void R_BuildNormalizationCube(void)
328 vec_t s, t, intensity;
330 unsigned char data[6][NORMSIZE][NORMSIZE][4];
331 for (side = 0;side < 6;side++)
333 for (y = 0;y < NORMSIZE;y++)
335 for (x = 0;x < NORMSIZE;x++)
337 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
338 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
373 intensity = 127.0f / sqrt(DotProduct(v, v));
374 data[side][y][x][0] = 128.0f + intensity * v[0];
375 data[side][y][x][1] = 128.0f + intensity * v[1];
376 data[side][y][x][2] = 128.0f + intensity * v[2];
377 data[side][y][x][3] = 255;
381 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
384 static void R_BuildFogTexture(void)
389 unsigned char data1[FOGWIDTH][4];
390 unsigned char data2[FOGWIDTH][4];
391 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
392 for (x = 0;x < FOGWIDTH;x++)
394 alpha = exp(r / ((double)x*(double)x));
395 if (x == FOGWIDTH - 1)
397 b = (int)(256.0 * alpha);
398 b = bound(0, b, 255);
399 data1[x][0] = 255 - b;
400 data1[x][1] = 255 - b;
401 data1[x][2] = 255 - b;
408 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
409 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
412 static const char *builtinshaderstring =
413 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
414 "// written by Forest 'LordHavoc' Hale\n"
416 "// common definitions between vertex shader and fragment shader:\n"
418 "// use half floats if available for math performance\n"
420 "#define myhalf half\n"
421 "#define myhvec2 hvec2\n"
422 "#define myhvec3 hvec3\n"
423 "#define myhvec4 hvec4\n"
425 "#define myhalf float\n"
426 "#define myhvec2 vec2\n"
427 "#define myhvec3 vec3\n"
428 "#define myhvec4 vec4\n"
431 "varying vec2 TexCoord;\n"
432 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
433 "varying vec2 TexCoordLightmap;\n"
436 "#ifdef MODE_LIGHTSOURCE\n"
437 "varying myhvec3 CubeVector;\n"
440 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
441 "varying vec3 LightVector;\n"
444 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
445 "varying vec3 EyeVector;\n"
448 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
449 "varying myhvec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
450 "varying myhvec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
451 "varying myhvec3 VectorR; // direction of R texcoord (surface normal)\n"
457 "// vertex shader specific:\n"
458 "#ifdef VERTEX_SHADER\n"
460 "#ifdef MODE_LIGHTSOURCE\n"
461 "uniform vec3 LightPosition;\n"
464 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
465 "uniform vec3 EyePosition;\n"
468 "#ifdef MODE_LIGHTDIRECTION\n"
469 "uniform myhvec3 LightDir;\n"
472 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
476 " // copy the surface texcoord\n"
477 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
478 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
479 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
481 " gl_FrontColor = gl_Color;\n"
483 "#ifdef MODE_LIGHTSOURCE\n"
484 " // transform vertex position into light attenuation/cubemap space\n"
485 " // (-1 to +1 across the light box)\n"
486 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
488 " // transform unnormalized light direction into tangent space\n"
489 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
490 " // normalize it per pixel)\n"
491 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
492 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
493 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
494 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
497 "#ifdef MODE_LIGHTDIRECTION\n"
498 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
499 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
500 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
503 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
504 " // transform unnormalized eye direction into tangent space\n"
505 " vec3 eyeminusvertex = EyePosition - gl_Vertex.xyz;\n"
506 " EyeVector.x = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);\n"
507 " EyeVector.y = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);\n"
508 " EyeVector.z = dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n"
511 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
512 " VectorS = gl_MultiTexCoord1.xyz;\n"
513 " VectorT = gl_MultiTexCoord2.xyz;\n"
514 " VectorR = gl_MultiTexCoord3.xyz;\n"
517 " // transform vertex to camera space, using ftransform to match non-VS\n"
519 " gl_Position = ftransform();\n"
527 "// fragment shader specific:\n"
528 "#ifdef FRAGMENT_SHADER\n"
530 "uniform myhvec3 LightColor;\n"
531 "#ifdef USEOFFSETMAPPING\n"
532 "uniform myhalf OffsetMapping_Scale;\n"
533 "uniform myhalf OffsetMapping_Bias;\n"
536 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE) || defined(MODE_LIGHTDIRECTION) || defined(USEOFFSETMAPPING)\n"
537 "uniform sampler2D Texture_Normal;\n"
540 "#ifdef MODE_LIGHTDIRECTION\n"
541 "uniform myhvec3 AmbientColor;\n"
542 "uniform myhvec3 DiffuseColor;\n"
543 "uniform myhvec3 SpecularColor;\n"
546 "uniform sampler2D Texture_Color;\n"
548 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
549 "uniform sampler2D Texture_Lightmap;\n"
551 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
552 "uniform sampler2D Texture_Deluxemap;\n"
556 "uniform sampler2D Texture_Glow;\n"
559 "#ifdef USECOLORMAPPING\n"
560 "uniform sampler2D Texture_Pants;\n"
561 "uniform sampler2D Texture_Shirt;\n"
562 "uniform myhvec3 Color_Pants;\n"
563 "uniform myhvec3 Color_Shirt;\n"
566 "uniform myhalf AmbientScale;\n"
567 "uniform myhalf DiffuseScale;\n"
568 "#ifdef USESPECULAR\n"
569 "uniform myhalf SpecularScale;\n"
570 "uniform myhalf SpecularPower;\n"
571 "uniform sampler2D Texture_Gloss;\n"
574 "#ifdef USECUBEFILTER\n"
575 "uniform samplerCube Texture_Cube;\n"
579 "uniform myhvec3 FogColor;\n"
580 "uniform myhalf FogRangeRecip;\n"
581 "uniform sampler2D Texture_FogMask;\n"
584 "#ifdef USEEASTEREGG\n"
587 " gl_FragColor = myhvec4(0, 0, 0, 1);;\n"
590 " vec2 p = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
591 " vec2 c = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
592 " for (i = 0;i < 1000 && dot(p,p) < 4.0;i = i + 1)\n"
594 " o = p.x * p.x - p.y * p.y;\n"
595 " p.y = 2.0 * p.x * p.y;\n"
599 " o = float(i) * 0.314;\n"
601 " gl_FragColor = vec4(cos(o), sin(o), sin(o * 0.2), 1);\n"
603 "#else // USEEASTEREGG\n"
609 " // apply offsetmapping\n"
610 "#ifdef USEOFFSETMAPPING\n"
611 " myhvec3 eyedir = myhvec3(normalize(EyeVector));\n"
612 " myhalf depthbias = 1.0 - eyedir.z; // should this be a -?\n"
613 " depthbias = 1.0 - depthbias * depthbias;\n"
614 " // this is 3 sample because of ATI Radeon 9500-9800/X300 limits\n"
615 " myhvec2 OffsetVector = (EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * vec2(-0.333, 0.333);\n"
616 " myhvec2 TexCoordOffset = TexCoord + OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).w);\n"
617 " TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoordOffset).w);\n"
618 " TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoordOffset).w);\n"
619 "#define TexCoord TexCoordOffset\n"
622 " // combine the diffuse textures (base, pants, shirt)\n"
623 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
624 "#ifdef USECOLORMAPPING\n"
625 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
631 "#ifdef MODE_LIGHTSOURCE\n"
634 " // get the surface normal and light normal\n"
635 "#ifdef SURFACENORMALIZE\n"
636 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
638 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
640 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
642 " // calculate directional shading\n"
643 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
644 "#ifdef USESPECULAR\n"
645 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
646 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
649 "#ifdef USECUBEFILTER\n"
650 " // apply light cubemap filter\n"
651 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
654 " // apply light color\n"
655 " color.rgb = color.rgb * LightColor;\n"
657 " // apply attenuation\n"
659 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
660 " // center and sharp falloff at the edge, this is about the most efficient\n"
661 " // we can get away with as far as providing illumination.\n"
663 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
664 " // provide significant illumination, large = slow = pain.\n"
665 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
670 "#elif defined(MODE_LIGHTDIRECTION)\n"
671 " // directional model lighting\n"
673 " // get the surface normal and light normal\n"
674 "#ifdef SURFACENORMALIZE\n"
675 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
677 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
679 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
682 " // calculate directional shading\n"
683 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
684 "#ifdef USESPECULAR\n"
685 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
686 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
692 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE)\n"
693 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
695 " // get the surface normal and light normal\n"
696 "#ifdef SURFACENORMALIZE\n"
697 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
699 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
701 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5;\n"
702 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, VectorS), dot(diffusenormal_modelspace, VectorT), dot(diffusenormal_modelspace, VectorR)));\n"
704 " // calculate directional shading\n"
705 " myhvec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
706 "#ifdef USESPECULAR\n"
707 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
708 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
711 " // apply lightmap color\n"
712 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * myhvec3(AmbientScale);\n"
717 "#elif defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
718 " // deluxemap lightmapping using light vectors in tangentspace\n"
720 " // get the surface normal and light normal\n"
721 "#ifdef SURFACENORMALIZE\n"
722 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
723 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
725 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
726 " myhvec3 diffusenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap));\n"
729 " // calculate directional shading\n"
730 " myhvec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
731 "#ifdef USESPECULAR\n"
732 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
733 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
736 " // apply lightmap color\n"
737 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * myhvec3(AmbientScale);\n"
742 "#else // MODE none (lightmap)\n"
743 " // apply lightmap color\n"
744 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
748 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord));\n"
753 " myhalf fog = texture2D(Texture_FogMask, myhvec2(length(EyeVector)*FogRangeRecip, 0.0)).x;\n"
754 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
757 " gl_FragColor = color * gl_Color;\n"
759 "#endif // !USEEASTEREGG\n"
764 void R_GLSL_CompilePermutation(int permutation)
766 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
767 int vertstrings_count;
768 int fragstrings_count;
770 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
771 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
772 char permutationname[256];
776 vertstrings_list[0] = "#define VERTEX_SHADER\n";
777 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
778 vertstrings_count = 1;
779 fragstrings_count = 1;
780 permutationname[0] = 0;
781 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
783 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
784 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
785 strlcat(permutationname, " lightsource", sizeof(permutationname));
787 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE)
789 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
790 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n";
791 strlcat(permutationname, " lightdirectionmap_modelspace", sizeof(permutationname));
793 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)
795 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
796 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n";
797 strlcat(permutationname, " lightdirectionmap_tangentspace", sizeof(permutationname));
799 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
801 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
802 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
803 strlcat(permutationname, " lightdirection", sizeof(permutationname));
805 if (permutation & SHADERPERMUTATION_GLOW)
807 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
808 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
809 strlcat(permutationname, " glow", sizeof(permutationname));
811 if (permutation & SHADERPERMUTATION_COLORMAPPING)
813 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
814 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
815 strlcat(permutationname, " colormapping", sizeof(permutationname));
817 if (permutation & SHADERPERMUTATION_SPECULAR)
819 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
820 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
821 strlcat(permutationname, " specular", sizeof(permutationname));
823 if (permutation & SHADERPERMUTATION_FOG)
825 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
826 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
827 strlcat(permutationname, " fog", sizeof(permutationname));
829 if (permutation & SHADERPERMUTATION_CUBEFILTER)
831 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
832 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
833 strlcat(permutationname, " cubefilter", sizeof(permutationname));
835 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
837 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
838 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
839 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
841 if (permutation & SHADERPERMUTATION_SURFACENORMALIZE)
843 vertstrings_list[vertstrings_count++] = "#define SURFACENORMALIZE\n";
844 fragstrings_list[fragstrings_count++] = "#define SURFACENORMALIZE\n";
845 strlcat(permutationname, " surfacenormalize", sizeof(permutationname));
847 if (permutation & SHADERPERMUTATION_GEFORCEFX)
849 vertstrings_list[vertstrings_count++] = "#define GEFORCEFX\n";
850 fragstrings_list[fragstrings_count++] = "#define GEFORCEFX\n";
851 strlcat(permutationname, " halffloat", sizeof(permutationname));
853 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
856 Con_DPrintf("GLSL shader text loaded from disk\n");
857 vertstrings_list[vertstrings_count++] = shaderstring;
858 fragstrings_list[fragstrings_count++] = shaderstring;
862 vertstrings_list[vertstrings_count++] = builtinshaderstring;
863 fragstrings_list[fragstrings_count++] = builtinshaderstring;
865 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
869 qglUseProgramObjectARB(p->program);
870 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
871 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
872 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
873 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
874 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
875 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
876 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
877 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
878 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
879 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
880 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
881 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
882 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
883 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
884 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
885 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
886 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
887 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
888 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
889 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
890 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
891 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
892 p->loc_OffsetMapping_Bias = qglGetUniformLocationARB(p->program, "OffsetMapping_Bias");
893 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
894 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
895 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
896 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
897 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
898 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
899 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
900 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
901 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
902 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
903 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
904 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
905 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
906 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
907 qglUseProgramObjectARB(0);
911 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
913 Mem_Free(shaderstring);
916 void R_GLSL_Restart_f(void)
919 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
920 if (r_glsl_permutations[i].program)
921 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
922 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
925 void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting)
927 // select a permutation of the lighting shader appropriate to this
928 // combination of texture, entity, light source, and fogging, only use the
929 // minimum features necessary to avoid wasting rendering time in the
930 // fragment shader on features that are not being used
932 float specularscale = texture->specularscale;
933 r_glsl_permutation = NULL;
934 if (r_shadow_rtlight)
936 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
937 specularscale *= r_shadow_rtlight->specularscale;
938 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
939 permutation |= SHADERPERMUTATION_CUBEFILTER;
944 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
945 else if (r_glsl_deluxemapping.integer >= 1 && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
947 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
948 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
950 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
952 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
953 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
954 if (texture->skin.glow)
955 permutation |= SHADERPERMUTATION_GLOW;
957 if (specularscale > 0)
958 permutation |= SHADERPERMUTATION_SPECULAR;
960 permutation |= SHADERPERMUTATION_FOG;
961 if (texture->colormapping)
962 permutation |= SHADERPERMUTATION_COLORMAPPING;
963 if (r_glsl_offsetmapping.integer)
964 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
965 if (r_glsl_surfacenormalize.integer)
966 permutation |= SHADERPERMUTATION_SURFACENORMALIZE;
967 if (r_glsl_usehalffloat.integer)
968 permutation |= SHADERPERMUTATION_GEFORCEFX;
969 if (!r_glsl_permutations[permutation].program)
971 if (!r_glsl_permutations[permutation].compiled)
972 R_GLSL_CompilePermutation(permutation);
973 if (!r_glsl_permutations[permutation].program)
975 // remove features until we find a valid permutation
977 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
979 // reduce i more quickly whenever it would not remove any bits
983 if (!r_glsl_permutations[permutation].compiled)
984 R_GLSL_CompilePermutation(permutation);
985 if (r_glsl_permutations[permutation].program)
988 return; // utterly failed
992 r_glsl_permutation = r_glsl_permutations + permutation;
994 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
995 R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
996 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
998 R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
999 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
1000 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);
1001 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1002 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
1003 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
1004 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1006 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
1008 if (texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1010 if (r_glsl_permutation->loc_AmbientColor >= 0)
1011 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, 1, 1, 1);
1012 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1013 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, 0, 0, 0);
1014 if (r_glsl_permutation->loc_SpecularColor >= 0)
1015 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, 0, 0, 0);
1016 if (r_glsl_permutation->loc_LightDir >= 0)
1017 qglUniform3fARB(r_glsl_permutation->loc_LightDir, 0, 0, -1);
1021 if (r_glsl_permutation->loc_AmbientColor >= 0)
1022 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
1023 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1024 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
1025 if (r_glsl_permutation->loc_SpecularColor >= 0)
1026 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
1027 if (r_glsl_permutation->loc_LightDir >= 0)
1028 qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->modellight_lightdir[2]);
1033 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
1034 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
1035 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale * 2.0f);
1037 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(texture->skin.nmap));
1038 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
1039 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
1040 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
1041 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
1042 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
1043 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
1044 if (r_glsl_permutation->loc_FogColor >= 0)
1046 // additive passes are only darkened by fog, not tinted
1047 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
1048 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1050 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
1052 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
1053 if (r_glsl_permutation->loc_Color_Pants >= 0)
1055 if (texture->skin.pants)
1056 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
1058 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1060 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1062 if (texture->skin.shirt)
1063 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
1065 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1067 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
1068 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
1069 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1070 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Bias, r_glsl_offsetmapping_bias.value);
1074 void gl_main_start(void)
1076 // use half float math where available (speed gain on NVIDIA GFFX and GF6)
1077 if (gl_support_half_float)
1078 Cvar_SetValue("r_glsl_usehalffloat", 1);
1079 r_main_texturepool = R_AllocTexturePool();
1080 r_bloom_texture_screen = NULL;
1081 r_bloom_texture_bloom = NULL;
1082 R_BuildBlankTextures();
1084 if (gl_texturecubemap)
1087 R_BuildNormalizationCube();
1089 R_BuildFogTexture();
1090 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1093 void gl_main_shutdown(void)
1095 R_FreeTexturePool(&r_main_texturepool);
1096 r_bloom_texture_screen = NULL;
1097 r_bloom_texture_bloom = NULL;
1098 r_texture_blanknormalmap = NULL;
1099 r_texture_white = NULL;
1100 r_texture_black = NULL;
1101 r_texture_whitecube = NULL;
1102 r_texture_normalizationcube = NULL;
1106 extern void CL_ParseEntityLump(char *entitystring);
1107 void gl_main_newmap(void)
1109 // FIXME: move this code to client
1111 char *entities, entname[MAX_QPATH];
1115 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1116 l = (int)strlen(entname) - 4;
1117 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1119 strcpy(entname + l, ".ent");
1120 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1122 CL_ParseEntityLump(entities);
1127 if (cl.worldmodel->brush.entities)
1128 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1132 void GL_Main_Init(void)
1134 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1136 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1137 FOG_registercvars(); // FIXME: move this fog stuff to client?
1138 Cvar_RegisterVariable(&r_nearclip);
1139 Cvar_RegisterVariable(&r_showtris);
1140 Cvar_RegisterVariable(&r_showtris_polygonoffset);
1141 Cvar_RegisterVariable(&r_shownormals);
1142 Cvar_RegisterVariable(&r_showlighting);
1143 Cvar_RegisterVariable(&r_showshadowvolumes);
1144 Cvar_RegisterVariable(&r_showcollisionbrushes);
1145 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1146 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1147 Cvar_RegisterVariable(&r_showdisabledepthtest);
1148 Cvar_RegisterVariable(&r_drawentities);
1149 Cvar_RegisterVariable(&r_drawviewmodel);
1150 Cvar_RegisterVariable(&r_speeds);
1151 Cvar_RegisterVariable(&r_fullbrights);
1152 Cvar_RegisterVariable(&r_wateralpha);
1153 Cvar_RegisterVariable(&r_dynamic);
1154 Cvar_RegisterVariable(&r_fullbright);
1155 Cvar_RegisterVariable(&r_textureunits);
1156 Cvar_RegisterVariable(&r_glsl);
1157 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1158 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1159 Cvar_RegisterVariable(&r_glsl_offsetmapping_bias);
1160 Cvar_RegisterVariable(&r_glsl_usehalffloat);
1161 Cvar_RegisterVariable(&r_glsl_surfacenormalize);
1162 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1163 Cvar_RegisterVariable(&r_lerpsprites);
1164 Cvar_RegisterVariable(&r_lerpmodels);
1165 Cvar_RegisterVariable(&r_waterscroll);
1166 Cvar_RegisterVariable(&r_bloom);
1167 Cvar_RegisterVariable(&r_bloom_intensity);
1168 Cvar_RegisterVariable(&r_bloom_blur);
1169 Cvar_RegisterVariable(&r_bloom_resolution);
1170 Cvar_RegisterVariable(&r_bloom_power);
1171 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1172 Cvar_RegisterVariable(&developer_texturelogging);
1173 Cvar_RegisterVariable(&gl_lightmaps);
1174 Cvar_RegisterVariable(&r_test);
1175 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1176 Cvar_SetValue("r_fullbrights", 0);
1177 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1180 static vec3_t r_farclip_origin;
1181 static vec3_t r_farclip_direction;
1182 static vec_t r_farclip_directiondist;
1183 static vec_t r_farclip_meshfarclip;
1184 static int r_farclip_directionbit0;
1185 static int r_farclip_directionbit1;
1186 static int r_farclip_directionbit2;
1188 // enlarge farclip to accomodate box
1189 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1192 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1193 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1194 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1195 if (r_farclip_meshfarclip < d)
1196 r_farclip_meshfarclip = d;
1199 // return farclip value
1200 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1204 VectorCopy(origin, r_farclip_origin);
1205 VectorCopy(direction, r_farclip_direction);
1206 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1207 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1208 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1209 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1210 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1212 if (r_refdef.worldmodel)
1213 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1214 for (i = 0;i < r_refdef.numentities;i++)
1215 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1217 return r_farclip_meshfarclip - r_farclip_directiondist;
1220 extern void R_Textures_Init(void);
1221 extern void GL_Draw_Init(void);
1222 extern void GL_Main_Init(void);
1223 extern void R_Shadow_Init(void);
1224 extern void R_Sky_Init(void);
1225 extern void GL_Surf_Init(void);
1226 extern void R_Crosshairs_Init(void);
1227 extern void R_Light_Init(void);
1228 extern void R_Particles_Init(void);
1229 extern void R_Explosion_Init(void);
1230 extern void gl_backend_init(void);
1231 extern void Sbar_Init(void);
1232 extern void R_LightningBeams_Init(void);
1233 extern void Mod_RenderInit(void);
1235 void Render_Init(void)
1245 R_Crosshairs_Init();
1250 R_LightningBeams_Init();
1259 extern char *ENGINE_EXTENSIONS;
1262 VID_CheckExtensions();
1264 // LordHavoc: report supported extensions
1265 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1267 // clear to black (loading plaque will be seen over this)
1268 qglClearColor(0,0,0,1);
1269 qglClear(GL_COLOR_BUFFER_BIT);
1272 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1276 for (i = 0;i < 4;i++)
1283 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1287 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1291 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1295 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1299 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1303 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1307 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1311 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1319 //==================================================================================
1321 static void R_UpdateEntityLighting(entity_render_t *ent)
1323 vec3_t tempdiffusenormal;
1324 VectorSet(ent->modellight_ambient, r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f));
1325 VectorClear(ent->modellight_diffuse);
1326 VectorClear(ent->modellight_lightdir);
1327 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1328 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1330 VectorSet(ent->modellight_ambient, 1, 1, 1);
1331 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1332 VectorNormalize(ent->modellight_lightdir);
1333 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1334 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1335 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1336 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1337 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1338 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1341 static void R_MarkEntities (void)
1344 entity_render_t *ent;
1346 if (!r_drawentities.integer)
1349 r_refdef.worldentity->visframe = r_framecount;
1350 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1351 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1353 // worldmodel can check visibility
1354 for (i = 0;i < r_refdef.numentities;i++)
1356 ent = r_refdef.entities[i];
1357 // some of the renderer still relies on origin...
1358 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1359 // some of the renderer still relies on scale...
1360 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1361 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)))
1363 ent->visframe = r_framecount;
1364 R_UpdateEntityLighting(ent);
1370 // no worldmodel or it can't check visibility
1371 for (i = 0;i < r_refdef.numentities;i++)
1373 ent = r_refdef.entities[i];
1374 // some of the renderer still relies on origin...
1375 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1376 // some of the renderer still relies on scale...
1377 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1378 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1380 ent->visframe = r_framecount;
1381 R_UpdateEntityLighting(ent);
1387 // only used if skyrendermasked, and normally returns false
1388 int R_DrawBrushModelsSky (void)
1391 entity_render_t *ent;
1393 if (!r_drawentities.integer)
1397 for (i = 0;i < r_refdef.numentities;i++)
1399 ent = r_refdef.entities[i];
1400 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1402 ent->model->DrawSky(ent);
1409 void R_DrawNoModel(entity_render_t *ent);
1410 void R_DrawModels(void)
1413 entity_render_t *ent;
1415 if (!r_drawentities.integer)
1418 for (i = 0;i < r_refdef.numentities;i++)
1420 ent = r_refdef.entities[i];
1421 if (ent->visframe == r_framecount)
1423 renderstats.entities++;
1424 if (ent->model && ent->model->Draw != NULL)
1425 ent->model->Draw(ent);
1432 static void R_SetFrustum(void)
1434 // break apart the view matrix into vectors for various purposes
1435 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1436 VectorNegate(r_viewleft, r_viewright);
1439 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1440 frustum[0].normal[1] = 0 - 0;
1441 frustum[0].normal[2] = -1 - 0;
1442 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1443 frustum[1].normal[1] = 0 + 0;
1444 frustum[1].normal[2] = -1 + 0;
1445 frustum[2].normal[0] = 0 - 0;
1446 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1447 frustum[2].normal[2] = -1 - 0;
1448 frustum[3].normal[0] = 0 + 0;
1449 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1450 frustum[3].normal[2] = -1 + 0;
1454 zNear = r_nearclip.value;
1455 nudge = 1.0 - 1.0 / (1<<23);
1456 frustum[4].normal[0] = 0 - 0;
1457 frustum[4].normal[1] = 0 - 0;
1458 frustum[4].normal[2] = -1 - -nudge;
1459 frustum[4].dist = 0 - -2 * zNear * nudge;
1460 frustum[5].normal[0] = 0 + 0;
1461 frustum[5].normal[1] = 0 + 0;
1462 frustum[5].normal[2] = -1 + -nudge;
1463 frustum[5].dist = 0 + -2 * zNear * nudge;
1469 frustum[0].normal[0] = m[3] - m[0];
1470 frustum[0].normal[1] = m[7] - m[4];
1471 frustum[0].normal[2] = m[11] - m[8];
1472 frustum[0].dist = m[15] - m[12];
1474 frustum[1].normal[0] = m[3] + m[0];
1475 frustum[1].normal[1] = m[7] + m[4];
1476 frustum[1].normal[2] = m[11] + m[8];
1477 frustum[1].dist = m[15] + m[12];
1479 frustum[2].normal[0] = m[3] - m[1];
1480 frustum[2].normal[1] = m[7] - m[5];
1481 frustum[2].normal[2] = m[11] - m[9];
1482 frustum[2].dist = m[15] - m[13];
1484 frustum[3].normal[0] = m[3] + m[1];
1485 frustum[3].normal[1] = m[7] + m[5];
1486 frustum[3].normal[2] = m[11] + m[9];
1487 frustum[3].dist = m[15] + m[13];
1489 frustum[4].normal[0] = m[3] - m[2];
1490 frustum[4].normal[1] = m[7] - m[6];
1491 frustum[4].normal[2] = m[11] - m[10];
1492 frustum[4].dist = m[15] - m[14];
1494 frustum[5].normal[0] = m[3] + m[2];
1495 frustum[5].normal[1] = m[7] + m[6];
1496 frustum[5].normal[2] = m[11] + m[10];
1497 frustum[5].dist = m[15] + m[14];
1502 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1503 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1504 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1505 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1506 VectorCopy(r_viewforward, frustum[4].normal);
1507 VectorNormalize(frustum[0].normal);
1508 VectorNormalize(frustum[1].normal);
1509 VectorNormalize(frustum[2].normal);
1510 VectorNormalize(frustum[3].normal);
1511 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1512 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1513 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1514 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1515 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1516 PlaneClassify(&frustum[0]);
1517 PlaneClassify(&frustum[1]);
1518 PlaneClassify(&frustum[2]);
1519 PlaneClassify(&frustum[3]);
1520 PlaneClassify(&frustum[4]);
1522 // LordHavoc: note to all quake engine coders, Quake had a special case
1523 // for 90 degrees which assumed a square view (wrong), so I removed it,
1524 // Quake2 has it disabled as well.
1526 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1527 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1528 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1529 //PlaneClassify(&frustum[0]);
1531 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1532 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1533 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1534 //PlaneClassify(&frustum[1]);
1536 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1537 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1538 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1539 //PlaneClassify(&frustum[2]);
1541 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1542 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1543 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1544 //PlaneClassify(&frustum[3]);
1547 //VectorCopy(r_viewforward, frustum[4].normal);
1548 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1549 //PlaneClassify(&frustum[4]);
1552 static void R_BlendView(void)
1554 int screenwidth, screenheight;
1559 // set the (poorly named) screenwidth and screenheight variables to
1560 // a power of 2 at least as large as the screen, these will define the
1561 // size of the texture to allocate
1562 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1563 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1565 doblend = r_refdef.viewblend[3] >= 0.01f;
1566 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;
1568 if (!dobloom && !doblend)
1571 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1573 GL_DepthTest(false);
1574 R_Mesh_Matrix(&identitymatrix);
1575 // vertex coordinates for a quad that covers the screen exactly
1576 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
1577 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
1578 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
1579 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
1582 int bloomwidth, bloomheight, x, dobloomblend, range;
1583 float xoffset, yoffset, r;
1584 renderstats.bloom++;
1585 // allocate textures as needed
1586 if (!r_bloom_texture_screen)
1587 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1588 if (!r_bloom_texture_bloom)
1589 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1590 // set bloomwidth and bloomheight to the bloom resolution that will be
1591 // used (often less than the screen resolution for faster rendering)
1592 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1593 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1594 // set up a texcoord array for the full resolution screen image
1595 // (we have to keep this around to copy back during final render)
1596 varray_texcoord2f[0][0] = 0;
1597 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1598 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1599 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1600 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1601 varray_texcoord2f[0][5] = 0;
1602 varray_texcoord2f[0][6] = 0;
1603 varray_texcoord2f[0][7] = 0;
1604 // set up a texcoord array for the reduced resolution bloom image
1605 // (which will be additive blended over the screen image)
1606 varray_texcoord2f[1][0] = 0;
1607 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1608 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1609 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1610 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1611 varray_texcoord2f[1][5] = 0;
1612 varray_texcoord2f[1][6] = 0;
1613 varray_texcoord2f[1][7] = 0;
1614 memset(&m, 0, sizeof(m));
1615 m.pointer_vertex = varray_vertex3f;
1616 m.pointer_texcoord[0] = varray_texcoord2f[0];
1617 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1619 // copy view into the full resolution screen image texture
1620 GL_ActiveTexture(0);
1621 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1622 renderstats.bloom_copypixels += r_view_width * r_view_height;
1623 // now scale it down to the bloom size and raise to a power of itself
1624 // to darken it (this leaves the really bright stuff bright, and
1625 // everything else becomes very dark)
1626 // TODO: optimize with multitexture or GLSL
1627 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1628 GL_BlendFunc(GL_ONE, GL_ZERO);
1629 GL_Color(1, 1, 1, 1);
1630 R_Mesh_Draw(0, 4, 2, polygonelements);
1631 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1632 // render multiple times with a multiply blendfunc to raise to a power
1633 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1634 for (x = 1;x < r_bloom_power.integer;x++)
1636 R_Mesh_Draw(0, 4, 2, polygonelements);
1637 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1639 // we now have a darkened bloom image in the framebuffer, copy it into
1640 // the bloom image texture for more processing
1641 memset(&m, 0, sizeof(m));
1642 m.pointer_vertex = varray_vertex3f;
1643 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1644 m.pointer_texcoord[0] = varray_texcoord2f[2];
1646 GL_ActiveTexture(0);
1647 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1648 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1649 // blend on at multiple vertical offsets to achieve a vertical blur
1650 // TODO: do offset blends using GLSL
1651 range = r_bloom_blur.integer * bloomwidth / 320;
1652 GL_BlendFunc(GL_ONE, GL_ZERO);
1653 for (x = -range;x <= range;x++)
1655 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1656 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1657 // compute a texcoord array with the specified x and y offset
1658 varray_texcoord2f[2][0] = xoffset+0;
1659 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1660 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1661 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1662 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1663 varray_texcoord2f[2][5] = yoffset+0;
1664 varray_texcoord2f[2][6] = xoffset+0;
1665 varray_texcoord2f[2][7] = yoffset+0;
1666 // this r value looks like a 'dot' particle, fading sharply to
1667 // black at the edges
1668 // (probably not realistic but looks good enough)
1669 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1672 GL_Color(r, r, r, 1);
1673 R_Mesh_Draw(0, 4, 2, polygonelements);
1674 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1675 GL_BlendFunc(GL_ONE, GL_ONE);
1677 // copy the vertically blurred bloom view to a texture
1678 GL_ActiveTexture(0);
1679 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1680 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1681 // blend the vertically blurred image at multiple offsets horizontally
1682 // to finish the blur effect
1683 // TODO: do offset blends using GLSL
1684 range = r_bloom_blur.integer * bloomwidth / 320;
1685 GL_BlendFunc(GL_ONE, GL_ZERO);
1686 for (x = -range;x <= range;x++)
1688 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1689 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1690 // compute a texcoord array with the specified x and y offset
1691 varray_texcoord2f[2][0] = xoffset+0;
1692 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1693 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1694 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1695 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1696 varray_texcoord2f[2][5] = yoffset+0;
1697 varray_texcoord2f[2][6] = xoffset+0;
1698 varray_texcoord2f[2][7] = yoffset+0;
1699 // this r value looks like a 'dot' particle, fading sharply to
1700 // black at the edges
1701 // (probably not realistic but looks good enough)
1702 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1705 GL_Color(r, r, r, 1);
1706 R_Mesh_Draw(0, 4, 2, polygonelements);
1707 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1708 GL_BlendFunc(GL_ONE, GL_ONE);
1710 // copy the blurred bloom view to a texture
1711 GL_ActiveTexture(0);
1712 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1713 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1714 // go back to full view area
1715 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1716 // put the original screen image back in place and blend the bloom
1718 memset(&m, 0, sizeof(m));
1719 m.pointer_vertex = varray_vertex3f;
1720 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1721 m.pointer_texcoord[0] = varray_texcoord2f[0];
1723 dobloomblend = false;
1725 // do both in one pass if possible
1726 if (r_textureunits.integer >= 2 && gl_combine.integer)
1728 dobloomblend = false;
1729 m.texcombinergb[1] = GL_ADD;
1730 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1731 m.pointer_texcoord[1] = varray_texcoord2f[1];
1734 dobloomblend = true;
1737 GL_BlendFunc(GL_ONE, GL_ZERO);
1739 R_Mesh_Draw(0, 4, 2, polygonelements);
1740 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1741 // now blend on the bloom texture if multipass
1744 memset(&m, 0, sizeof(m));
1745 m.pointer_vertex = varray_vertex3f;
1746 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1747 m.pointer_texcoord[0] = varray_texcoord2f[1];
1749 GL_BlendFunc(GL_ONE, GL_ONE);
1751 R_Mesh_Draw(0, 4, 2, polygonelements);
1752 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1757 // apply a color tint to the whole view
1758 memset(&m, 0, sizeof(m));
1759 m.pointer_vertex = varray_vertex3f;
1761 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1762 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1763 R_Mesh_Draw(0, 4, 2, polygonelements);
1767 void R_RenderScene(void);
1769 matrix4x4_t r_waterscrollmatrix;
1776 void R_RenderView(void)
1778 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1779 return; //Host_Error ("R_RenderView: NULL worldmodel");
1781 r_view_width = bound(0, r_refdef.width, vid.width);
1782 r_view_height = bound(0, r_refdef.height, vid.height);
1784 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1785 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1787 r_view_matrix = r_refdef.viewentitymatrix;
1788 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1789 r_rtworld = r_shadow_realtime_world.integer;
1790 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1791 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1792 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1793 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1795 // GL is weird because it's bottom to top, r_view_y is top to bottom
1796 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1797 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1798 GL_ScissorTest(true);
1803 if (r_timereport_active)
1804 R_TimeReport("setup");
1806 qglDepthFunc(GL_LEQUAL);
1807 qglPolygonOffset(0, 0);
1808 qglEnable(GL_POLYGON_OFFSET_FILL);
1812 qglPolygonOffset(0, 0);
1813 qglDisable(GL_POLYGON_OFFSET_FILL);
1816 if (r_timereport_active)
1817 R_TimeReport("blendview");
1819 GL_Scissor(0, 0, vid.width, vid.height);
1820 GL_ScissorTest(false);
1824 void CSQC_R_ClearScreen (void)
1826 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1827 return; //Host_Error ("R_RenderView: NULL worldmodel");
1829 r_view_width = bound(0, r_refdef.width, vid.width);
1830 r_view_height = bound(0, r_refdef.height, vid.height);
1832 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1833 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1835 r_view_matrix = r_refdef.viewentitymatrix;
1836 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1837 r_rtworld = r_shadow_realtime_world.integer;
1838 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1839 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1840 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1841 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1843 // GL is weird because it's bottom to top, r_view_y is top to bottom
1844 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1845 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1846 GL_ScissorTest(true);
1851 if (r_timereport_active)
1852 R_TimeReport("setup");
1856 void CSQC_R_RenderScene (void)
1858 qglDepthFunc(GL_LEQUAL);
1859 qglPolygonOffset(0, 0);
1860 qglEnable(GL_POLYGON_OFFSET_FILL);
1864 qglPolygonOffset(0, 0);
1865 qglDisable(GL_POLYGON_OFFSET_FILL);
1868 if (r_timereport_active)
1869 R_TimeReport("blendview");
1871 GL_Scissor(0, 0, vid.width, vid.height);
1872 GL_ScissorTest(false);
1875 extern void R_DrawLightningBeams (void);
1876 extern void VM_AddPolygonsToMeshQueue (void);
1877 void R_RenderScene(void)
1881 // don't let sound skip if going slow
1882 if (r_refdef.extraupdate)
1887 if (gl_support_fragment_shader)
1888 qglUseProgramObjectARB(0);
1890 R_MeshQueue_BeginScene();
1894 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1895 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1897 if (r_rtworldshadows || r_rtdlightshadows)
1898 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1900 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1902 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1904 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);
1908 R_WorldVisibility();
1909 if (r_timereport_active)
1910 R_TimeReport("worldvis");
1913 if (r_timereport_active)
1914 R_TimeReport("markentity");
1916 R_Shadow_UpdateWorldLightSelection();
1918 for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1924 GL_BlendFunc(GL_ONE, GL_ONE);
1925 GL_DepthTest(!r_showdisabledepthtest.integer);
1926 GL_DepthMask(GL_FALSE);
1927 memset(&m, 0, sizeof(m));
1929 //qglEnable(GL_LINE_SMOOTH);
1930 qglEnable(GL_POLYGON_OFFSET_LINE);
1931 qglPolygonOffset(0, r_showtris_polygonoffset.value);
1935 if (cl.csqc_vidvars.drawworld)
1937 // don't let sound skip if going slow
1938 if (r_refdef.extraupdate)
1942 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1943 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1945 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1946 if (r_timereport_active)
1947 R_TimeReport("worldsky");
1950 if (R_DrawBrushModelsSky() && r_timereport_active)
1951 R_TimeReport("bmodelsky");
1954 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1955 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1957 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1958 if (r_timereport_active)
1959 R_TimeReport("world");
1963 // don't let sound skip if going slow
1964 if (r_refdef.extraupdate)
1968 GL_ShowTrisColor(0, 0.015, 0, 1);
1971 if (r_timereport_active)
1972 R_TimeReport("models");
1974 // don't let sound skip if going slow
1975 if (r_refdef.extraupdate)
1979 GL_ShowTrisColor(0, 0, 0.033, 1);
1980 R_ShadowVolumeLighting(false);
1981 if (r_timereport_active)
1982 R_TimeReport("rtlights");
1984 // don't let sound skip if going slow
1985 if (r_refdef.extraupdate)
1989 GL_ShowTrisColor(0.1, 0, 0, 1);
1991 if (cl.csqc_vidvars.drawworld)
1993 R_DrawLightningBeams();
1994 if (r_timereport_active)
1995 R_TimeReport("lightning");
1998 if (r_timereport_active)
1999 R_TimeReport("particles");
2002 if (r_timereport_active)
2003 R_TimeReport("explosions");
2006 R_MeshQueue_RenderTransparent();
2007 if (r_timereport_active)
2008 R_TimeReport("drawtrans");
2010 if (cl.csqc_vidvars.drawworld)
2013 if (r_timereport_active)
2014 R_TimeReport("coronas");
2016 if(cl.csqc_vidvars.drawcrosshair)
2018 R_DrawWorldCrosshair();
2019 if (r_timereport_active)
2020 R_TimeReport("crosshair");
2023 VM_AddPolygonsToMeshQueue();
2025 R_MeshQueue_Render();
2029 //qglDisable(GL_LINE_SMOOTH);
2030 qglDisable(GL_POLYGON_OFFSET_LINE);
2036 R_MeshQueue_EndScene();
2038 // don't let sound skip if going slow
2039 if (r_refdef.extraupdate)
2042 if (gl_support_fragment_shader)
2043 qglUseProgramObjectARB(0);
2047 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2050 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2052 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2053 GL_DepthMask(false);
2055 R_Mesh_Matrix(&identitymatrix);
2057 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2058 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2059 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2060 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2061 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2062 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2063 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2064 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2065 R_FillColors(color, 8, cr, cg, cb, ca);
2068 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2070 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
2072 c[0] = c[0] * f1 + fogcolor[0] * f2;
2073 c[1] = c[1] * f1 + fogcolor[1] * f2;
2074 c[2] = c[2] * f1 + fogcolor[2] * f2;
2077 memset(&m, 0, sizeof(m));
2078 m.pointer_vertex = vertex3f;
2079 m.pointer_color = color;
2085 int nomodelelements[24] =
2097 float nomodelvertex3f[6*3] =
2107 float nomodelcolor4f[6*4] =
2109 0.0f, 0.0f, 0.5f, 1.0f,
2110 0.0f, 0.0f, 0.5f, 1.0f,
2111 0.0f, 0.5f, 0.0f, 1.0f,
2112 0.0f, 0.5f, 0.0f, 1.0f,
2113 0.5f, 0.0f, 0.0f, 1.0f,
2114 0.5f, 0.0f, 0.0f, 1.0f
2117 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2123 R_Mesh_Matrix(&ent->matrix);
2125 memset(&m, 0, sizeof(m));
2126 m.pointer_vertex = nomodelvertex3f;
2128 if (ent->flags & EF_ADDITIVE)
2130 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2131 GL_DepthMask(false);
2133 else if (ent->alpha < 1)
2135 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2136 GL_DepthMask(false);
2140 GL_BlendFunc(GL_ONE, GL_ZERO);
2143 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2146 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2147 m.pointer_color = color4f;
2148 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2150 for (i = 0, c = color4f;i < 6;i++, c += 4)
2152 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2153 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2154 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2158 else if (ent->alpha != 1)
2160 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2161 m.pointer_color = color4f;
2162 for (i = 0, c = color4f;i < 6;i++, c += 4)
2166 m.pointer_color = nomodelcolor4f;
2168 R_Mesh_Draw(0, 6, 8, nomodelelements);
2171 void R_DrawNoModel(entity_render_t *ent)
2173 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2174 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2176 // R_DrawNoModelCallback(ent, 0);
2179 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2181 vec3_t right1, right2, diff, normal;
2183 VectorSubtract (org2, org1, normal);
2185 // calculate 'right' vector for start
2186 VectorSubtract (r_vieworigin, org1, diff);
2187 CrossProduct (normal, diff, right1);
2188 VectorNormalize (right1);
2190 // calculate 'right' vector for end
2191 VectorSubtract (r_vieworigin, org2, diff);
2192 CrossProduct (normal, diff, right2);
2193 VectorNormalize (right2);
2195 vert[ 0] = org1[0] + width * right1[0];
2196 vert[ 1] = org1[1] + width * right1[1];
2197 vert[ 2] = org1[2] + width * right1[2];
2198 vert[ 3] = org1[0] - width * right1[0];
2199 vert[ 4] = org1[1] - width * right1[1];
2200 vert[ 5] = org1[2] - width * right1[2];
2201 vert[ 6] = org2[0] - width * right2[0];
2202 vert[ 7] = org2[1] - width * right2[1];
2203 vert[ 8] = org2[2] - width * right2[2];
2204 vert[ 9] = org2[0] + width * right2[0];
2205 vert[10] = org2[1] + width * right2[1];
2206 vert[11] = org2[2] + width * right2[2];
2209 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2211 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)
2213 float fog = 0.0f, ifog;
2217 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2220 R_Mesh_Matrix(&identitymatrix);
2221 GL_BlendFunc(blendfunc1, blendfunc2);
2222 GL_DepthMask(false);
2223 GL_DepthTest(!depthdisable);
2225 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2226 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2227 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2228 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2229 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2230 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2231 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2232 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2233 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2234 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2235 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2236 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2238 memset(&m, 0, sizeof(m));
2239 m.tex[0] = R_GetTexture(texture);
2240 m.pointer_texcoord[0] = spritetexcoord2f;
2241 m.pointer_vertex = varray_vertex3f;
2243 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2244 R_Mesh_Draw(0, 4, 2, polygonelements);
2246 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2248 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2249 GL_BlendFunc(blendfunc1, GL_ONE);
2250 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2251 R_Mesh_Draw(0, 4, 2, polygonelements);
2255 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2259 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2260 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2262 if (i == mesh->numvertices)
2264 if (mesh->numvertices < mesh->maxvertices)
2266 VectorCopy(v, vertex3f);
2267 mesh->numvertices++;
2269 return mesh->numvertices;
2275 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2279 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2280 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2281 e = mesh->element3i + mesh->numtriangles * 3;
2282 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2284 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2285 if (mesh->numtriangles < mesh->maxtriangles)
2290 mesh->numtriangles++;
2292 element[1] = element[2];
2296 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2298 int planenum, planenum2;
2301 mplane_t *plane, *plane2;
2302 float temppoints[2][256*3];
2303 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2307 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2308 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2310 if (planenum2 == planenum)
2312 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, NULL);
2315 if (tempnumpoints < 3)
2317 // generate elements forming a triangle fan for this polygon
2318 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2322 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
2324 texturelayer_t *layer;
2325 layer = t->currentlayers + t->currentnumlayers++;
2327 layer->depthmask = depthmask;
2328 layer->blendfunc1 = blendfunc1;
2329 layer->blendfunc2 = blendfunc2;
2330 layer->texture = texture;
2331 layer->texmatrix = *matrix;
2332 layer->color[0] = r;
2333 layer->color[1] = g;
2334 layer->color[2] = b;
2335 layer->color[3] = a;
2338 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2340 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2341 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2344 texture_t *texture = t;
2345 model_t *model = ent->model;
2346 int s = ent->skinnum;
2347 if ((unsigned int)s >= (unsigned int)model->numskins)
2349 if (model->skinscenes)
2351 if (model->skinscenes[s].framecount > 1)
2352 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2354 s = model->skinscenes[s].firstframe;
2357 t = t + s * model->num_surfaces;
2359 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];
2360 texture->currentframe = t;
2363 t->currentmaterialflags = t->basematerialflags;
2364 t->currentalpha = ent->alpha;
2365 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2366 t->currentalpha *= r_wateralpha.value;
2367 if (!(ent->flags & RENDER_LIGHT))
2368 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2369 if (ent->effects & EF_ADDITIVE)
2370 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2371 else if (t->currentalpha < 1)
2372 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2373 if (ent->effects & EF_NODEPTHTEST)
2374 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2375 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2376 t->currenttexmatrix = r_waterscrollmatrix;
2378 t->currenttexmatrix = identitymatrix;
2380 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2381 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2382 t->glosstexture = r_texture_white;
2383 t->specularpower = 8;
2384 t->specularscale = 0;
2385 if (r_shadow_gloss.integer > 0)
2389 if (r_shadow_glossintensity.value > 0)
2391 t->glosstexture = t->skin.gloss;
2392 t->specularscale = r_shadow_glossintensity.value;
2395 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2396 t->specularscale = r_shadow_gloss2intensity.value;
2399 t->currentnumlayers = 0;
2400 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2402 if (gl_lightmaps.integer)
2403 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2404 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2406 int blendfunc1, blendfunc2, depthmask;
2407 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2409 blendfunc1 = GL_SRC_ALPHA;
2410 blendfunc2 = GL_ONE;
2413 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2415 blendfunc1 = GL_SRC_ALPHA;
2416 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2421 blendfunc1 = GL_ONE;
2422 blendfunc2 = GL_ZERO;
2425 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2427 rtexture_t *currentbasetexture;
2429 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2430 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2431 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2432 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2434 // fullbright is not affected by r_lightmapintensity
2435 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2436 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2437 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
2438 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2439 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0], ent->colormap_shirtcolor[1] * ent->colormod[1], ent->colormap_shirtcolor[2] * ent->colormod[2], t->currentalpha);
2445 // q3bsp has no lightmap updates, so the lightstylevalue that
2446 // would normally be baked into the lightmaptexture must be
2447 // applied to the color
2448 if (ent->model->type == mod_brushq3)
2449 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2450 colorscale *= r_lightmapintensity;
2451 if (r_textureunits.integer >= 2 && gl_combine.integer)
2452 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, t->currentalpha);
2453 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2454 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, t->currentalpha);
2456 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, t->currentalpha);
2457 if (r_ambient.value >= (1.0f/64.0f))
2458 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), t->currentalpha);
2459 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2461 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
2462 if (r_ambient.value >= (1.0f/64.0f))
2463 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
2465 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2467 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE_VERTEX, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
2468 if (r_ambient.value >= (1.0f/64.0f))
2469 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
2472 if (t->skin.glow != NULL)
2473 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2474 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2476 // if this is opaque use alpha blend which will darken the earlier
2479 // if this is an alpha blended material, all the earlier passes
2480 // were darkened by fog already, so we only need to add the fog
2481 // color ontop through the fog mask texture
2483 // if this is an additive blended material, all the earlier passes
2484 // were darkened by fog already, and we should not add fog color
2485 // (because the background was not darkened, there is no fog color
2486 // that was lost behind it).
2487 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->skin.fog, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], t->currentalpha);
2494 void R_UpdateAllTextureInfo(entity_render_t *ent)
2498 for (i = 0;i < ent->model->num_textures;i++)
2499 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2502 float *rsurface_vertex3f;
2503 float *rsurface_svector3f;
2504 float *rsurface_tvector3f;
2505 float *rsurface_normal3f;
2506 float *rsurface_lightmapcolor4f;
2508 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
2510 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
2512 rsurface_vertex3f = varray_vertex3f;
2513 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
2514 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2516 rsurface_svector3f = varray_svector3f;
2517 rsurface_tvector3f = varray_tvector3f;
2518 rsurface_normal3f = varray_normal3f;
2519 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);
2523 rsurface_svector3f = NULL;
2524 rsurface_tvector3f = NULL;
2525 if (generatenormals)
2527 rsurface_normal3f = varray_normal3f;
2528 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);
2531 rsurface_normal3f = NULL;
2536 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
2537 rsurface_svector3f = surface->groupmesh->data_svector3f;
2538 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
2539 rsurface_normal3f = surface->groupmesh->data_normal3f;
2541 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2544 float center[3], forward[3], right[3], up[3], v[4][3];
2545 matrix4x4_t matrix1, imatrix1;
2546 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
2547 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
2548 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
2549 // a single autosprite surface can contain multiple sprites...
2550 for (j = 0;j < surface->num_vertices - 3;j += 4)
2552 VectorClear(center);
2553 for (i = 0;i < 4;i++)
2554 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2555 VectorScale(center, 0.25f, center);
2556 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2557 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);
2558 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2559 for (i = 0;i < 4;i++)
2560 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2561 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2563 forward[0] = modelorg[0] - center[0];
2564 forward[1] = modelorg[1] - center[1];
2566 VectorNormalize(forward);
2567 right[0] = forward[1];
2568 right[1] = -forward[0];
2570 VectorSet(up, 0, 0, 1);
2572 for (i = 0;i < 4;i++)
2573 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
2575 rsurface_vertex3f = varray_vertex3f;
2576 rsurface_svector3f = varray_svector3f;
2577 rsurface_tvector3f = varray_tvector3f;
2578 rsurface_normal3f = varray_normal3f;
2579 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);
2581 R_Mesh_VertexPointer(rsurface_vertex3f);
2584 static void RSurf_Draw(const msurface_t *surface)
2586 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2587 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2588 GL_LockArrays(0, 0);
2591 static void RSurf_DrawLightmap(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2596 RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode >= 2, false);
2600 vec3_t ambientcolor;
2601 vec3_t diffusecolor;
2603 VectorCopy(ent->modellight_lightdir, lightdir);
2604 ambientcolor[0] = ent->modellight_ambient[0] * r * 0.5f;
2605 ambientcolor[1] = ent->modellight_ambient[1] * g * 0.5f;
2606 ambientcolor[2] = ent->modellight_ambient[2] * b * 0.5f;
2607 diffusecolor[0] = ent->modellight_diffuse[0] * r * 0.5f;
2608 diffusecolor[1] = ent->modellight_diffuse[1] * g * 0.5f;
2609 diffusecolor[2] = ent->modellight_diffuse[2] * b * 0.5f;
2610 if (VectorLength2(diffusecolor) > 0)
2612 int numverts = surface->num_vertices;
2613 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2614 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2615 c = varray_color4f + 4 * surface->num_firstvertex;
2616 // q3-style directional shading
2617 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2619 if ((f = DotProduct(c2, lightdir)) > 0)
2620 VectorMA(ambientcolor, f, diffusecolor, c);
2622 VectorCopy(ambientcolor, c);
2630 rsurface_lightmapcolor4f = varray_color4f;
2634 r = ambientcolor[0];
2635 g = ambientcolor[1];
2636 b = ambientcolor[2];
2637 rsurface_lightmapcolor4f = NULL;
2640 else if (lightmode >= 1)
2642 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2644 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2646 if (surface->lightmapinfo->samples)
2648 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
2649 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2650 VectorScale(lm, scale, c);
2651 if (surface->lightmapinfo->styles[1] != 255)
2653 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2655 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2656 VectorMA(c, scale, lm, c);
2657 if (surface->lightmapinfo->styles[2] != 255)
2660 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2661 VectorMA(c, scale, lm, c);
2662 if (surface->lightmapinfo->styles[3] != 255)
2665 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2666 VectorMA(c, scale, lm, c);
2674 rsurface_lightmapcolor4f = varray_color4f;
2677 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
2680 rsurface_lightmapcolor4f = NULL;
2683 if (rsurface_lightmapcolor4f)
2685 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)
2687 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2696 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)
2698 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2705 rsurface_lightmapcolor4f = varray_color4f;
2707 if (applycolor && rsurface_lightmapcolor4f)
2709 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)
2716 rsurface_lightmapcolor4f = varray_color4f;
2718 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2719 GL_Color(r, g, b, a);
2720 RSurf_Draw(surface);
2723 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2725 int texturesurfaceindex;
2727 const msurface_t *surface;
2728 qboolean applycolor;
2731 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2733 r_shadow_rtlight = NULL;
2734 renderstats.entities_surfaces += texturenumsurfaces;
2735 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2736 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2737 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2738 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2739 qglDisable(GL_CULL_FACE);
2740 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2742 // transparent sky would be ridiculous
2743 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2748 skyrendernow = false;
2749 if (skyrendermasked)
2752 // restore entity matrix and GL_Color
2753 R_Mesh_Matrix(&ent->matrix);
2757 // LordHavoc: HalfLife maps have freaky skypolys...
2758 //if (!ent->model->brush.ishlbsp)
2760 if (skyrendermasked)
2762 // depth-only (masking)
2763 GL_ColorMask(0,0,0,0);
2764 // just to make sure that braindead drivers don't draw anything
2765 // despite that colormask...
2766 GL_BlendFunc(GL_ZERO, GL_ONE);
2771 GL_BlendFunc(GL_ONE, GL_ZERO);
2773 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2774 memset(&m, 0, sizeof(m));
2776 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2778 surface = texturesurfacelist[texturesurfaceindex];
2779 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2780 RSurf_Draw(surface);
2782 if (skyrendermasked)
2783 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2787 else if (r_glsl.integer && gl_support_fragment_shader)
2789 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2791 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2792 GL_DepthMask(false);
2794 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2796 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2797 GL_DepthMask(false);
2801 GL_BlendFunc(GL_ONE, GL_ZERO);
2805 memset(&m, 0, sizeof(m));
2807 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2808 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2809 if (!r_glsl_permutation)
2813 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2815 surface = texturesurfacelist[texturesurfaceindex];
2816 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2817 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2818 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2819 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2820 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2821 RSurf_Draw(surface);
2826 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2828 surface = texturesurfacelist[texturesurfaceindex];
2829 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2830 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2831 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2832 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2833 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2834 R_Mesh_TexCoordPointer(4, 2, surface->groupmesh->data_texcoordlightmap2f);
2835 if (surface->lightmaptexture)
2837 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2838 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2839 R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2840 R_Mesh_ColorPointer(NULL);
2844 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2845 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2846 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2847 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2849 RSurf_Draw(surface);
2852 qglUseProgramObjectARB(0);
2854 else if (texture->currentnumlayers)
2857 texturelayer_t *layer;
2858 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2861 int layertexrgbscale;
2862 GL_DepthMask(layer->depthmask);
2863 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2864 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2866 layertexrgbscale = 4;
2867 VectorScale(layer->color, 0.25f, layercolor);
2869 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2871 layertexrgbscale = 2;
2872 VectorScale(layer->color, 0.5f, layercolor);
2876 layertexrgbscale = 1;
2877 VectorScale(layer->color, 1.0f, layercolor);
2879 layercolor[3] = layer->color[3];
2880 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2881 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2882 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2883 switch (layer->type)
2885 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2886 memset(&m, 0, sizeof(m));
2887 m.tex[1] = R_GetTexture(layer->texture);
2888 m.texmatrix[1] = layer->texmatrix;
2889 m.texrgbscale[1] = layertexrgbscale;
2890 m.pointer_color = varray_color4f;
2894 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2896 surface = texturesurfacelist[texturesurfaceindex];
2897 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2898 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2899 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2900 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2905 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2907 surface = texturesurfacelist[texturesurfaceindex];
2908 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2909 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2910 if (surface->lightmaptexture)
2912 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2913 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2917 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2918 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2923 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2924 memset(&m, 0, sizeof(m));
2925 m.tex[0] = R_GetTexture(layer->texture);
2926 m.texmatrix[0] = layer->texmatrix;
2927 m.pointer_color = varray_color4f;
2928 m.texrgbscale[0] = layertexrgbscale;
2932 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2934 surface = texturesurfacelist[texturesurfaceindex];
2935 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2936 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2937 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2942 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2944 surface = texturesurfacelist[texturesurfaceindex];
2945 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2946 if (surface->lightmaptexture)
2948 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2949 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
2953 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2954 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2958 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2959 memset(&m, 0, sizeof(m));
2960 m.tex[0] = R_GetTexture(layer->texture);
2961 m.texmatrix[0] = layer->texmatrix;
2962 m.pointer_color = varray_color4f;
2963 m.texrgbscale[0] = layertexrgbscale;
2965 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2967 surface = texturesurfacelist[texturesurfaceindex];
2968 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2969 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2972 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2973 memset(&m, 0, sizeof(m));
2974 m.tex[0] = R_GetTexture(layer->texture);
2975 m.texmatrix[0] = layer->texmatrix;
2976 m.texrgbscale[0] = layertexrgbscale;
2977 m.pointer_color = varray_color4f;
2981 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2983 surface = texturesurfacelist[texturesurfaceindex];
2984 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2985 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2990 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2992 surface = texturesurfacelist[texturesurfaceindex];
2993 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2994 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2998 case TEXTURELAYERTYPE_TEXTURE:
2999 memset(&m, 0, sizeof(m));
3000 m.tex[0] = R_GetTexture(layer->texture);
3001 m.texmatrix[0] = layer->texmatrix;
3002 m.pointer_color = varray_color4f;
3003 m.texrgbscale[0] = layertexrgbscale;
3005 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3007 surface = texturesurfacelist[texturesurfaceindex];
3008 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3009 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3012 case TEXTURELAYERTYPE_FOG:
3013 memset(&m, 0, sizeof(m));
3016 m.tex[0] = R_GetTexture(layer->texture);
3017 m.texmatrix[0] = layer->texmatrix;
3020 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3024 surface = texturesurfacelist[texturesurfaceindex];
3025 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
3027 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
3028 R_Mesh_ColorPointer(varray_color4f);
3029 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)
3031 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
3032 c[0] = layercolor[0];
3033 c[1] = layercolor[1];
3034 c[2] = layercolor[2];
3035 c[3] = f * layercolor[3];
3037 RSurf_Draw(surface);
3041 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3043 // if trying to do overbright on first pass of an opaque surface
3044 // when combine is not supported, brighten as a post process
3045 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3048 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3049 GL_Color(1, 1, 1, 1);
3050 memset(&m, 0, sizeof(m));
3052 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3054 surface = texturesurfacelist[texturesurfaceindex];
3055 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
3056 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3057 RSurf_Draw(surface);
3061 if (r_shownormals.integer && !r_showtrispass)
3065 GL_DepthTest(!r_showdisabledepthtest.integer);
3066 GL_DepthMask(texture->currentlayers->depthmask);
3067 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
3068 memset(&m, 0, sizeof(m));
3070 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3072 surface = texturesurfacelist[texturesurfaceindex];
3073 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
3074 GL_Color(1, 0, 0, 1);
3076 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3078 VectorCopy(rsurface_vertex3f + k * 3, v);
3079 qglVertex3f(v[0], v[1], v[2]);
3080 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
3081 qglVertex3f(v[0], v[1], v[2]);
3083 GL_Color(0, 0, 1, 1);
3084 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3086 VectorCopy(rsurface_vertex3f + k * 3, v);
3087 qglVertex3f(v[0], v[1], v[2]);
3088 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
3089 qglVertex3f(v[0], v[1], v[2]);
3091 GL_Color(0, 1, 0, 1);
3092 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3094 VectorCopy(rsurface_vertex3f + k * 3, v);
3095 qglVertex3f(v[0], v[1], v[2]);
3096 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
3097 qglVertex3f(v[0], v[1], v[2]);
3103 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3104 qglEnable(GL_CULL_FACE);
3107 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3109 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3113 texture = surface->texture;
3114 if (texture->basematerialflags & MATERIALFLAG_SKY)
3115 return; // transparent sky is too difficult
3116 R_UpdateTextureInfo(ent, texture);
3118 R_Mesh_Matrix(&ent->matrix);
3119 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3120 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3123 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
3125 int texturesurfaceindex;
3126 const msurface_t *surface;
3127 vec3_t tempcenter, center;
3128 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3130 // drawing sky transparently would be too difficult
3131 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3133 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3135 surface = texturesurfacelist[texturesurfaceindex];
3136 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3137 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3138 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3139 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3140 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3145 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3148 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3149 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3151 int i, j, f, flagsmask;
3152 int counttriangles = 0;
3153 msurface_t *surface, **surfacechain;
3154 texture_t *t, *texture;
3155 model_t *model = ent->model;
3157 const int maxsurfacelist = 1024;
3158 int numsurfacelist = 0;
3159 const msurface_t *surfacelist[1024];
3162 R_Mesh_Matrix(&ent->matrix);
3163 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3165 // update light styles
3166 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3168 for (i = 0;i < model->brushq1.light_styles;i++)
3170 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3172 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3173 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3174 for (;(surface = *surfacechain);surfacechain++)
3175 surface->cached_dlight = true;
3180 R_UpdateAllTextureInfo(ent);
3181 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3186 if (ent == r_refdef.worldentity)
3188 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3190 if (!r_worldsurfacevisible[j])
3192 if (t != surface->texture)
3196 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3199 t = surface->texture;
3200 texture = t->currentframe;
3201 f = texture->currentmaterialflags & flagsmask;
3203 if (f && surface->num_triangles)
3205 // if lightmap parameters changed, rebuild lightmap texture
3206 if (surface->cached_dlight)
3207 R_BuildLightMap(ent, surface);
3208 // add face to draw list
3209 surfacelist[numsurfacelist++] = surface;
3210 counttriangles += surface->num_triangles;
3211 if (numsurfacelist >= maxsurfacelist)
3213 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3221 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3223 if (t != surface->texture)
3227 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3230 t = surface->texture;
3231 texture = t->currentframe;
3232 f = texture->currentmaterialflags & flagsmask;
3234 if (f && surface->num_triangles)
3236 // if lightmap parameters changed, rebuild lightmap texture
3237 if (surface->cached_dlight)
3238 R_BuildLightMap(ent, surface);
3239 // add face to draw list
3240 surfacelist[numsurfacelist++] = surface;
3241 counttriangles += surface->num_triangles;
3242 if (numsurfacelist >= maxsurfacelist)
3244 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3251 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3252 if (!r_showtrispass)
3253 renderstats.entities_triangles += counttriangles;
3254 if (gl_support_fragment_shader)
3255 qglUseProgramObjectARB(0);