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"};
108 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
109 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
110 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
112 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
113 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
114 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
115 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
116 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
118 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"};
120 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"};
122 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
124 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
126 rtexture_t *r_bloom_texture_screen;
127 rtexture_t *r_bloom_texture_bloom;
128 rtexture_t *r_texture_blanknormalmap;
129 rtexture_t *r_texture_white;
130 rtexture_t *r_texture_black;
131 rtexture_t *r_texture_notexture;
132 rtexture_t *r_texture_whitecube;
133 rtexture_t *r_texture_normalizationcube;
134 rtexture_t *r_texture_fogattenuation;
135 rtexture_t *r_texture_fogintensity;
137 // information about each possible shader permutation
138 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
139 // currently selected permutation
140 r_glsl_permutation_t *r_glsl_permutation;
142 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
145 for (i = 0;i < verts;i++)
156 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
159 for (i = 0;i < verts;i++)
174 vec_t fogtabledistmultiplier;
175 float fogtable[FOGTABLEWIDTH];
176 float fog_density, fog_red, fog_green, fog_blue;
178 qboolean oldgl_fogenable;
179 void R_UpdateFog(void)
181 if (gamemode == GAME_NEHAHRA)
183 if (gl_fogenable.integer)
185 oldgl_fogenable = true;
186 fog_density = gl_fogdensity.value;
187 fog_red = gl_fogred.value;
188 fog_green = gl_foggreen.value;
189 fog_blue = gl_fogblue.value;
191 else if (oldgl_fogenable)
193 oldgl_fogenable = false;
202 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
203 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
204 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
209 fogdensity = -4000.0f / (fog_density * fog_density);
210 // this is the point where the fog reaches 0.9986 alpha, which we
211 // consider a good enough cutoff point for the texture
212 // (0.9986 * 256 == 255.6)
213 fogrange = 400 / fog_density;
214 fograngerecip = 1.0f / fogrange;
215 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
216 // fog color was already set
222 // FIXME: move this to client?
225 if (gamemode == GAME_NEHAHRA)
227 Cvar_Set("gl_fogenable", "0");
228 Cvar_Set("gl_fogdensity", "0.2");
229 Cvar_Set("gl_fogred", "0.3");
230 Cvar_Set("gl_foggreen", "0.3");
231 Cvar_Set("gl_fogblue", "0.3");
233 fog_density = fog_red = fog_green = fog_blue = 0.0f;
236 // FIXME: move this to client?
237 void FOG_registercvars(void)
242 if (gamemode == GAME_NEHAHRA)
244 Cvar_RegisterVariable (&gl_fogenable);
245 Cvar_RegisterVariable (&gl_fogdensity);
246 Cvar_RegisterVariable (&gl_fogred);
247 Cvar_RegisterVariable (&gl_foggreen);
248 Cvar_RegisterVariable (&gl_fogblue);
249 Cvar_RegisterVariable (&gl_fogstart);
250 Cvar_RegisterVariable (&gl_fogend);
253 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
254 for (x = 0;x < FOGTABLEWIDTH;x++)
256 alpha = exp(r / ((double)x*(double)x));
257 if (x == FOGTABLEWIDTH - 1)
259 fogtable[x] = bound(0, alpha, 1);
263 static void R_BuildBlankTextures(void)
265 unsigned char data[4];
266 data[0] = 128; // normal X
267 data[1] = 128; // normal Y
268 data[2] = 255; // normal Z
269 data[3] = 128; // height
270 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
275 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
280 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
283 static void R_BuildNoTexture(void)
286 unsigned char pix[16][16][4];
287 // this makes a light grey/dark grey checkerboard texture
288 for (y = 0;y < 16;y++)
290 for (x = 0;x < 16;x++)
292 if ((y < 8) ^ (x < 8))
308 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
311 static void R_BuildWhiteCube(void)
313 unsigned char data[6*1*1*4];
314 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
315 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
316 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
317 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
318 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
319 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
320 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
323 static void R_BuildNormalizationCube(void)
327 vec_t s, t, intensity;
329 unsigned char data[6][NORMSIZE][NORMSIZE][4];
330 for (side = 0;side < 6;side++)
332 for (y = 0;y < NORMSIZE;y++)
334 for (x = 0;x < NORMSIZE;x++)
336 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
337 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
372 intensity = 127.0f / sqrt(DotProduct(v, v));
373 data[side][y][x][0] = 128.0f + intensity * v[0];
374 data[side][y][x][1] = 128.0f + intensity * v[1];
375 data[side][y][x][2] = 128.0f + intensity * v[2];
376 data[side][y][x][3] = 255;
380 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
383 static void R_BuildFogTexture(void)
388 unsigned char data1[FOGWIDTH][4];
389 unsigned char data2[FOGWIDTH][4];
390 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
391 for (x = 0;x < FOGWIDTH;x++)
393 alpha = exp(r / ((double)x*(double)x));
394 if (x == FOGWIDTH - 1)
396 b = (int)(256.0 * alpha);
397 b = bound(0, b, 255);
398 data1[x][0] = 255 - b;
399 data1[x][1] = 255 - b;
400 data1[x][2] = 255 - b;
407 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
408 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
411 static const char *builtinshaderstring =
412 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
413 "// written by Forest 'LordHavoc' Hale\n"
415 "// common definitions between vertex shader and fragment shader:\n"
417 "// use half floats if available for math performance\n"
419 "#define myhalf half\n"
420 "#define myhvec2 hvec2\n"
421 "#define myhvec3 hvec3\n"
422 "#define myhvec4 hvec4\n"
424 "#define myhalf float\n"
425 "#define myhvec2 vec2\n"
426 "#define myhvec3 vec3\n"
427 "#define myhvec4 vec4\n"
430 "varying vec2 TexCoord;\n"
432 "#ifdef USELIGHTSOURCE\n"
433 "varying myhvec3 CubeVector;\n"
434 "varying vec3 LightVector;\n"
437 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
438 "varying vec3 EyeVector;\n"
444 "// vertex shader specific:\n"
445 "#ifdef VERTEX_SHADER\n"
447 "#ifdef USELIGHTSOURCE\n"
448 "uniform vec3 LightPosition;\n"
451 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
452 "uniform vec3 EyePosition;\n"
455 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
459 " // copy the surface texcoord\n"
460 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
462 "#ifdef USELIGHTSOURCE\n"
463 " // transform vertex position into light attenuation/cubemap space\n"
464 " // (-1 to +1 across the light box)\n"
465 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
467 " // transform unnormalized light direction into tangent space\n"
468 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
469 " // normalize it per pixel)\n"
470 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
471 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
472 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
473 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
476 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
477 " // transform unnormalized eye direction into tangent space\n"
478 " vec3 eyeminusvertex = EyePosition - gl_Vertex.xyz;\n"
479 " EyeVector.x = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);\n"
480 " EyeVector.y = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);\n"
481 " EyeVector.z = dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n"
484 " // transform vertex to camera space, using ftransform to match non-VS\n"
486 " gl_Position = ftransform();\n"
494 "// fragment shader specific:\n"
495 "#ifdef FRAGMENT_SHADER\n"
497 "uniform myhvec3 LightColor;\n"
498 "#ifdef USEOFFSETMAPPING\n"
499 "uniform myhalf OffsetMapping_Scale;\n"
500 "uniform myhalf OffsetMapping_Bias;\n"
503 "#if defined(USELIGHTSOURCE) || defined(USEDELUXEMAPPING)\n"
504 "uniform sampler2D Texture_Normal;\n"
507 "uniform sampler2D Texture_Color;\n"
509 "#ifdef USECOLORMAPPING\n"
510 "uniform sampler2D Texture_Pants;\n"
511 "uniform sampler2D Texture_Shirt;\n"
512 "uniform myhvec3 Color_Pants;\n"
513 "uniform myhvec3 Color_Shirt;\n"
516 "uniform myhalf AmbientScale;\n"
517 "uniform myhalf DiffuseScale;\n"
518 "#ifdef USESPECULAR\n"
519 "uniform myhalf SpecularScale;\n"
520 "uniform myhalf SpecularPower;\n"
521 "uniform sampler2D Texture_Gloss;\n"
524 "#ifdef USECUBEFILTER\n"
525 "uniform samplerCube Texture_Cube;\n"
529 "uniform myhalf FogRangeRecip;\n"
530 "uniform sampler2D Texture_FogMask;\n"
535 " // apply offsetmapping\n"
536 "#ifdef USEOFFSETMAPPING\n"
537 " // this is 3 sample because of ATI Radeon 9500-9800/X300 limits\n"
538 " myhvec2 OffsetVector = normalize(EyeVector).xy * vec2(-0.333, 0.333);\n"
539 " myhvec2 TexCoordOffset = TexCoord + OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).w);\n"
540 " TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoordOffset).w);\n"
541 " TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoordOffset).w);\n"
542 "#define TexCoord TexCoordOffset\n"
545 " // combine the diffuse textures (base, pants, shirt)\n"
546 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
547 "#ifdef USECOLORMAPPING\n"
548 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
554 "#ifdef USELIGHTSOURCE\n"
557 " // get the surface normal and light normal\n"
558 "#ifdef SURFACENORMALIZE\n"
559 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
561 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
563 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
565 " // calculate directional shading\n"
566 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
567 "#ifdef USESPECULAR\n"
568 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
569 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
572 "#ifdef USECUBEFILTER\n"
573 " // apply light cubemap filter\n"
574 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
577 " // apply light color\n"
578 " color.rgb = color.rgb * LightColor;\n"
580 " // apply attenuation\n"
582 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
583 " // center and sharp falloff at the edge, this is about the most efficient\n"
584 " // we can get away with as far as providing illumination.\n"
586 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
587 " // provide significant illumination, large = slow = pain.\n"
588 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
594 "#ifdef USEDELUXEMAPPING\n"
595 " // deluxemap lightmapping\n"
597 " // get the surface normal and light normal\n"
598 "#ifdef SURFACENORMALIZE\n"
599 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
600 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)));\n"
602 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
603 " myhvec3 diffusenormal = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap));\n"
606 " // calculate directional shading\n"
607 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
608 "#ifdef USESPECULAR\n"
609 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
610 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
613 " // apply lightmap color\n"
614 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
620 " // apply lightmap color\n"
621 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale;\n"
630 " myhalf fog = texture2D(Texture_FogMask, myhvec2(length(EyeVector)*FogRangeRecip, 0)).x;\n"
631 " color.rgb = color.rgb * (1 - fog) + FogColor * fog;\n"
634 " gl_FragColor = color;\n"
640 // the loaded GLSL shader file for compiling shader permutations as needed
641 static char *shaderstring = NULL;
643 void R_GLSL_CompilePermutation(int permutation)
645 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
646 int vertstrings_count;
647 int fragstrings_count;
648 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
649 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
650 char permutationname[256];
654 vertstrings_list[0] = "#define VERTEX_SHADER\n";
655 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
656 vertstrings_count = 1;
657 fragstrings_count = 1;
658 permutationname[0] = 0;
659 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
661 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
662 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
663 strlcat(permutationname, " lightsource", sizeof(permutationname));
665 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP)
667 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP\n";
668 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP\n";
669 strlcat(permutationname, " lightdirectionmap", sizeof(permutationname));
671 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
673 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
674 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
675 strlcat(permutationname, " lightdirection", sizeof(permutationname));
677 if (permutation & SHADERPERMUTATION_GLOW)
679 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
680 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
681 strlcat(permutationname, " glow", sizeof(permutationname));
683 if (permutation & SHADERPERMUTATION_COLORMAPPING)
685 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
686 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
687 strlcat(permutationname, " colormapping", sizeof(permutationname));
689 if (permutation & SHADERPERMUTATION_SPECULAR)
691 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
692 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
693 strlcat(permutationname, " specular", sizeof(permutationname));
695 if (permutation & SHADERPERMUTATION_FOG)
697 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
698 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
699 strlcat(permutationname, " fog", sizeof(permutationname));
701 if (permutation & SHADERPERMUTATION_CUBEFILTER)
703 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
704 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
705 strlcat(permutationname, " cubefilter", sizeof(permutationname));
707 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
709 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
710 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
711 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
713 if (permutation & SHADERPERMUTATION_SURFACENORMALIZE)
715 vertstrings_list[vertstrings_count++] = "#define SURFACENORMALIZE\n";
716 fragstrings_list[fragstrings_count++] = "#define SURFACENORMALIZE\n";
717 strlcat(permutationname, " surfacenormalize", sizeof(permutationname));
719 if (permutation & SHADERPERMUTATION_GEFORCEFX)
721 vertstrings_list[vertstrings_count++] = "#define GEFORCEFX\n";
722 fragstrings_list[fragstrings_count++] = "#define GEFORCEFX\n";
723 strlcat(permutationname, " halffloat", sizeof(permutationname));
727 vertstrings_list[vertstrings_count++] = shaderstring;
728 fragstrings_list[fragstrings_count++] = shaderstring;
732 vertstrings_list[vertstrings_count++] = builtinshaderstring;
733 fragstrings_list[fragstrings_count++] = builtinshaderstring;
735 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
739 qglUseProgramObjectARB(p->program);
740 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
741 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
742 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
743 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
744 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
745 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
746 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
747 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
748 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
749 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
750 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
751 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
752 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
753 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
754 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
755 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
756 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
757 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
758 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
759 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
760 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
761 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
762 p->loc_OffsetMapping_Bias = qglGetUniformLocationARB(p->program, "OffsetMapping_Bias");
763 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
764 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
765 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
766 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
767 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
768 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
769 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
770 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
771 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
772 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
773 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
774 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
775 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
776 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
777 qglUseProgramObjectARB(0);
781 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
784 void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting)
786 // select a permutation of the lighting shader appropriate to this
787 // combination of texture, entity, light source, and fogging, only use the
788 // minimum features necessary to avoid wasting rendering time in the
789 // fragment shader on features that are not being used
791 float specularscale = texture->specularscale;
792 r_glsl_permutation = NULL;
793 if (r_shadow_rtlight)
795 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
796 specularscale *= r_shadow_rtlight->specularscale;
797 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
798 permutation |= SHADERPERMUTATION_CUBEFILTER;
800 else if (modellighting)
802 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
803 if (texture->skin.glow)
804 permutation |= SHADERPERMUTATION_GLOW;
808 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP;
809 if (texture->skin.glow)
810 permutation |= SHADERPERMUTATION_GLOW;
814 if (texture->skin.glow)
815 permutation |= SHADERPERMUTATION_GLOW;
817 if (specularscale > 0)
818 permutation |= SHADERPERMUTATION_SPECULAR;
820 permutation |= SHADERPERMUTATION_FOG;
821 if (texture->colormapping)
822 permutation |= SHADERPERMUTATION_COLORMAPPING;
823 if (r_glsl_offsetmapping.integer)
824 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
825 if (r_glsl_surfacenormalize.integer)
826 permutation |= SHADERPERMUTATION_SURFACENORMALIZE;
827 if (r_glsl_usehalffloat.integer)
828 permutation |= SHADERPERMUTATION_GEFORCEFX;
829 if (!r_glsl_permutations[permutation].program)
831 if (!r_glsl_permutations[permutation].compiled)
832 R_GLSL_CompilePermutation(permutation);
833 if (!r_glsl_permutations[permutation].program)
835 // remove features until we find a valid permutation
837 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
839 // reduce i more quickly whenever it would not remove any bits
843 if (!r_glsl_permutations[permutation].compiled)
844 R_GLSL_CompilePermutation(permutation);
845 if (r_glsl_permutations[permutation].program)
848 return; // utterly failed
852 r_glsl_permutation = r_glsl_permutations + permutation;
854 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
855 R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
856 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
858 R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
859 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
860 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]);
861 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
862 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
863 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
864 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
866 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
868 if (r_glsl_permutation->loc_AmbientColor >= 0)
869 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
870 if (r_glsl_permutation->loc_DiffuseColor >= 0)
871 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
872 if (r_glsl_permutation->loc_SpecularColor >= 0)
873 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
874 if (r_glsl_permutation->loc_LightDir >= 0)
875 qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->modellight_lightdir[2]);
879 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
880 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
881 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale * 2.0f);
883 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(texture->skin.nmap));
884 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
885 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
886 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
887 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
888 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
889 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
890 if (r_glsl_permutation->loc_FogColor >= 0)
892 // additive passes are only darkened by fog, not tinted
893 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
894 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
896 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
898 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
899 if (r_glsl_permutation->loc_Color_Pants >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
900 if (r_glsl_permutation->loc_Color_Shirt >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
901 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
902 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
903 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
904 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Bias, r_glsl_offsetmapping_bias.value);
908 void gl_main_start(void)
910 // use half float math where available (speed gain on NVIDIA GFFX and GF6)
911 if (gl_support_half_float)
912 Cvar_SetValue("r_glsl_usehalffloat", 1);
913 r_main_texturepool = R_AllocTexturePool();
914 r_bloom_texture_screen = NULL;
915 r_bloom_texture_bloom = NULL;
916 R_BuildBlankTextures();
918 if (gl_texturecubemap)
921 R_BuildNormalizationCube();
925 if (gl_support_fragment_shader)
927 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
929 Con_Printf("GLSL shader text loaded from disk\n");
930 // if we couldn't load the shader file, fall back to builtin shader
934 Con_Printf("GLSL shader text loaded from fallback\n");
935 shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
936 strcpy(shaderstring, builtinshaderstring);
940 Con_Printf("GLSL shader text loaded\n");
941 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
944 void gl_main_shutdown(void)
947 R_FreeTexturePool(&r_main_texturepool);
948 r_bloom_texture_screen = NULL;
949 r_bloom_texture_bloom = NULL;
950 r_texture_blanknormalmap = NULL;
951 r_texture_white = NULL;
952 r_texture_black = NULL;
953 r_texture_whitecube = NULL;
954 r_texture_normalizationcube = NULL;
956 Mem_Free(shaderstring);
958 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
959 if (r_glsl_permutations[i].program)
960 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
961 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
964 extern void CL_ParseEntityLump(char *entitystring);
965 void gl_main_newmap(void)
967 // FIXME: move this code to client
969 char *entities, entname[MAX_QPATH];
973 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
974 l = (int)strlen(entname) - 4;
975 if (l >= 0 && !strcmp(entname + l, ".bsp"))
977 strcpy(entname + l, ".ent");
978 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
980 CL_ParseEntityLump(entities);
985 if (cl.worldmodel->brush.entities)
986 CL_ParseEntityLump(cl.worldmodel->brush.entities);
990 void GL_Main_Init(void)
992 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
994 FOG_registercvars(); // FIXME: move this fog stuff to client?
995 Cvar_RegisterVariable(&r_nearclip);
996 Cvar_RegisterVariable(&r_showtris);
997 Cvar_RegisterVariable(&r_showtris_polygonoffset);
998 Cvar_RegisterVariable(&r_shownormals);
999 Cvar_RegisterVariable(&r_showlighting);
1000 Cvar_RegisterVariable(&r_showshadowvolumes);
1001 Cvar_RegisterVariable(&r_showcollisionbrushes);
1002 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1003 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1004 Cvar_RegisterVariable(&r_showdisabledepthtest);
1005 Cvar_RegisterVariable(&r_drawentities);
1006 Cvar_RegisterVariable(&r_drawviewmodel);
1007 Cvar_RegisterVariable(&r_speeds);
1008 Cvar_RegisterVariable(&r_fullbrights);
1009 Cvar_RegisterVariable(&r_wateralpha);
1010 Cvar_RegisterVariable(&r_dynamic);
1011 Cvar_RegisterVariable(&r_fullbright);
1012 Cvar_RegisterVariable(&r_textureunits);
1013 Cvar_RegisterVariable(&r_glsl);
1014 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1015 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1016 Cvar_RegisterVariable(&r_glsl_offsetmapping_bias);
1017 Cvar_RegisterVariable(&r_glsl_usehalffloat);
1018 Cvar_RegisterVariable(&r_glsl_surfacenormalize);
1019 Cvar_RegisterVariable(&r_lerpsprites);
1020 Cvar_RegisterVariable(&r_lerpmodels);
1021 Cvar_RegisterVariable(&r_waterscroll);
1022 Cvar_RegisterVariable(&r_bloom);
1023 Cvar_RegisterVariable(&r_bloom_intensity);
1024 Cvar_RegisterVariable(&r_bloom_blur);
1025 Cvar_RegisterVariable(&r_bloom_resolution);
1026 Cvar_RegisterVariable(&r_bloom_power);
1027 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1028 Cvar_RegisterVariable(&developer_texturelogging);
1029 Cvar_RegisterVariable(&gl_lightmaps);
1030 Cvar_RegisterVariable(&r_test);
1031 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1032 Cvar_SetValue("r_fullbrights", 0);
1033 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1036 static vec3_t r_farclip_origin;
1037 static vec3_t r_farclip_direction;
1038 static vec_t r_farclip_directiondist;
1039 static vec_t r_farclip_meshfarclip;
1040 static int r_farclip_directionbit0;
1041 static int r_farclip_directionbit1;
1042 static int r_farclip_directionbit2;
1044 // enlarge farclip to accomodate box
1045 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1048 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1049 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1050 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1051 if (r_farclip_meshfarclip < d)
1052 r_farclip_meshfarclip = d;
1055 // return farclip value
1056 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1060 VectorCopy(origin, r_farclip_origin);
1061 VectorCopy(direction, r_farclip_direction);
1062 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1063 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1064 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1065 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1066 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1068 if (r_refdef.worldmodel)
1069 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1070 for (i = 0;i < r_refdef.numentities;i++)
1071 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1073 return r_farclip_meshfarclip - r_farclip_directiondist;
1076 extern void R_Textures_Init(void);
1077 extern void GL_Draw_Init(void);
1078 extern void GL_Main_Init(void);
1079 extern void R_Shadow_Init(void);
1080 extern void R_Sky_Init(void);
1081 extern void GL_Surf_Init(void);
1082 extern void R_Crosshairs_Init(void);
1083 extern void R_Light_Init(void);
1084 extern void R_Particles_Init(void);
1085 extern void R_Explosion_Init(void);
1086 extern void gl_backend_init(void);
1087 extern void Sbar_Init(void);
1088 extern void R_LightningBeams_Init(void);
1089 extern void Mod_RenderInit(void);
1091 void Render_Init(void)
1101 R_Crosshairs_Init();
1106 R_LightningBeams_Init();
1115 extern char *ENGINE_EXTENSIONS;
1118 VID_CheckExtensions();
1120 // LordHavoc: report supported extensions
1121 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1123 // clear to black (loading plaque will be seen over this)
1124 qglClearColor(0,0,0,1);
1125 qglClear(GL_COLOR_BUFFER_BIT);
1128 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1132 for (i = 0;i < 4;i++)
1139 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1143 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1147 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1151 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1155 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1159 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1163 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1167 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1175 //==================================================================================
1177 static void R_UpdateEntityLighting(entity_render_t *ent)
1179 vec3_t tempdiffusenormal;
1180 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));
1181 VectorClear(ent->modellight_diffuse);
1182 VectorClear(ent->modellight_lightdir);
1183 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1184 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1186 VectorSet(ent->modellight_ambient, 1, 1, 1);
1187 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1188 VectorNormalize(ent->modellight_lightdir);
1189 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1190 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1191 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1192 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1193 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1194 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1197 static void R_MarkEntities (void)
1200 entity_render_t *ent;
1202 if (!r_drawentities.integer)
1205 r_refdef.worldentity->visframe = r_framecount;
1206 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1207 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1209 // worldmodel can check visibility
1210 for (i = 0;i < r_refdef.numentities;i++)
1212 ent = r_refdef.entities[i];
1213 // some of the renderer still relies on origin...
1214 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1215 // some of the renderer still relies on scale...
1216 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1217 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)))
1219 ent->visframe = r_framecount;
1220 R_UpdateEntityLighting(ent);
1226 // no worldmodel or it can't check visibility
1227 for (i = 0;i < r_refdef.numentities;i++)
1229 ent = r_refdef.entities[i];
1230 // some of the renderer still relies on origin...
1231 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1232 // some of the renderer still relies on scale...
1233 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1234 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1236 ent->visframe = r_framecount;
1237 R_UpdateEntityLighting(ent);
1243 // only used if skyrendermasked, and normally returns false
1244 int R_DrawBrushModelsSky (void)
1247 entity_render_t *ent;
1249 if (!r_drawentities.integer)
1253 for (i = 0;i < r_refdef.numentities;i++)
1255 ent = r_refdef.entities[i];
1256 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1258 ent->model->DrawSky(ent);
1265 void R_DrawNoModel(entity_render_t *ent);
1266 void R_DrawModels(void)
1269 entity_render_t *ent;
1271 if (!r_drawentities.integer)
1274 for (i = 0;i < r_refdef.numentities;i++)
1276 ent = r_refdef.entities[i];
1277 if (ent->visframe == r_framecount)
1279 renderstats.entities++;
1280 if (ent->model && ent->model->Draw != NULL)
1281 ent->model->Draw(ent);
1288 static void R_SetFrustum(void)
1290 // break apart the view matrix into vectors for various purposes
1291 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1292 VectorNegate(r_viewleft, r_viewright);
1295 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1296 frustum[0].normal[1] = 0 - 0;
1297 frustum[0].normal[2] = -1 - 0;
1298 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1299 frustum[1].normal[1] = 0 + 0;
1300 frustum[1].normal[2] = -1 + 0;
1301 frustum[2].normal[0] = 0 - 0;
1302 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1303 frustum[2].normal[2] = -1 - 0;
1304 frustum[3].normal[0] = 0 + 0;
1305 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1306 frustum[3].normal[2] = -1 + 0;
1310 zNear = r_nearclip.value;
1311 nudge = 1.0 - 1.0 / (1<<23);
1312 frustum[4].normal[0] = 0 - 0;
1313 frustum[4].normal[1] = 0 - 0;
1314 frustum[4].normal[2] = -1 - -nudge;
1315 frustum[4].dist = 0 - -2 * zNear * nudge;
1316 frustum[5].normal[0] = 0 + 0;
1317 frustum[5].normal[1] = 0 + 0;
1318 frustum[5].normal[2] = -1 + -nudge;
1319 frustum[5].dist = 0 + -2 * zNear * nudge;
1325 frustum[0].normal[0] = m[3] - m[0];
1326 frustum[0].normal[1] = m[7] - m[4];
1327 frustum[0].normal[2] = m[11] - m[8];
1328 frustum[0].dist = m[15] - m[12];
1330 frustum[1].normal[0] = m[3] + m[0];
1331 frustum[1].normal[1] = m[7] + m[4];
1332 frustum[1].normal[2] = m[11] + m[8];
1333 frustum[1].dist = m[15] + m[12];
1335 frustum[2].normal[0] = m[3] - m[1];
1336 frustum[2].normal[1] = m[7] - m[5];
1337 frustum[2].normal[2] = m[11] - m[9];
1338 frustum[2].dist = m[15] - m[13];
1340 frustum[3].normal[0] = m[3] + m[1];
1341 frustum[3].normal[1] = m[7] + m[5];
1342 frustum[3].normal[2] = m[11] + m[9];
1343 frustum[3].dist = m[15] + m[13];
1345 frustum[4].normal[0] = m[3] - m[2];
1346 frustum[4].normal[1] = m[7] - m[6];
1347 frustum[4].normal[2] = m[11] - m[10];
1348 frustum[4].dist = m[15] - m[14];
1350 frustum[5].normal[0] = m[3] + m[2];
1351 frustum[5].normal[1] = m[7] + m[6];
1352 frustum[5].normal[2] = m[11] + m[10];
1353 frustum[5].dist = m[15] + m[14];
1358 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1359 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1360 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1361 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1362 VectorCopy(r_viewforward, frustum[4].normal);
1363 VectorNormalize(frustum[0].normal);
1364 VectorNormalize(frustum[1].normal);
1365 VectorNormalize(frustum[2].normal);
1366 VectorNormalize(frustum[3].normal);
1367 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1368 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1369 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1370 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1371 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1372 PlaneClassify(&frustum[0]);
1373 PlaneClassify(&frustum[1]);
1374 PlaneClassify(&frustum[2]);
1375 PlaneClassify(&frustum[3]);
1376 PlaneClassify(&frustum[4]);
1378 // LordHavoc: note to all quake engine coders, Quake had a special case
1379 // for 90 degrees which assumed a square view (wrong), so I removed it,
1380 // Quake2 has it disabled as well.
1382 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1383 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1384 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1385 //PlaneClassify(&frustum[0]);
1387 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1388 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1389 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1390 //PlaneClassify(&frustum[1]);
1392 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1393 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1394 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1395 //PlaneClassify(&frustum[2]);
1397 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1398 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1399 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1400 //PlaneClassify(&frustum[3]);
1403 //VectorCopy(r_viewforward, frustum[4].normal);
1404 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1405 //PlaneClassify(&frustum[4]);
1408 static void R_BlendView(void)
1410 int screenwidth, screenheight;
1415 // set the (poorly named) screenwidth and screenheight variables to
1416 // a power of 2 at least as large as the screen, these will define the
1417 // size of the texture to allocate
1418 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1419 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1421 doblend = r_refdef.viewblend[3] >= 0.01f;
1422 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;
1424 if (!dobloom && !doblend)
1427 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1429 GL_DepthTest(false);
1430 R_Mesh_Matrix(&identitymatrix);
1431 // vertex coordinates for a quad that covers the screen exactly
1432 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
1433 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
1434 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
1435 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
1438 int bloomwidth, bloomheight, x, dobloomblend, range;
1439 float xoffset, yoffset, r;
1440 renderstats.bloom++;
1441 // allocate textures as needed
1442 if (!r_bloom_texture_screen)
1443 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1444 if (!r_bloom_texture_bloom)
1445 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1446 // set bloomwidth and bloomheight to the bloom resolution that will be
1447 // used (often less than the screen resolution for faster rendering)
1448 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1449 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1450 // set up a texcoord array for the full resolution screen image
1451 // (we have to keep this around to copy back during final render)
1452 varray_texcoord2f[0][0] = 0;
1453 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1454 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1455 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1456 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1457 varray_texcoord2f[0][5] = 0;
1458 varray_texcoord2f[0][6] = 0;
1459 varray_texcoord2f[0][7] = 0;
1460 // set up a texcoord array for the reduced resolution bloom image
1461 // (which will be additive blended over the screen image)
1462 varray_texcoord2f[1][0] = 0;
1463 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1464 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1465 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1466 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1467 varray_texcoord2f[1][5] = 0;
1468 varray_texcoord2f[1][6] = 0;
1469 varray_texcoord2f[1][7] = 0;
1470 memset(&m, 0, sizeof(m));
1471 m.pointer_vertex = varray_vertex3f;
1472 m.pointer_texcoord[0] = varray_texcoord2f[0];
1473 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1475 // copy view into the full resolution screen image texture
1476 GL_ActiveTexture(0);
1477 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1478 renderstats.bloom_copypixels += r_view_width * r_view_height;
1479 // now scale it down to the bloom size and raise to a power of itself
1480 // to darken it (this leaves the really bright stuff bright, and
1481 // everything else becomes very dark)
1482 // TODO: optimize with multitexture or GLSL
1483 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1484 GL_BlendFunc(GL_ONE, GL_ZERO);
1485 GL_Color(1, 1, 1, 1);
1486 R_Mesh_Draw(0, 4, 2, polygonelements);
1487 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1488 // render multiple times with a multiply blendfunc to raise to a power
1489 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1490 for (x = 1;x < r_bloom_power.integer;x++)
1492 R_Mesh_Draw(0, 4, 2, polygonelements);
1493 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1495 // we now have a darkened bloom image in the framebuffer, copy it into
1496 // the bloom image texture for more processing
1497 memset(&m, 0, sizeof(m));
1498 m.pointer_vertex = varray_vertex3f;
1499 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1500 m.pointer_texcoord[0] = varray_texcoord2f[2];
1502 GL_ActiveTexture(0);
1503 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1504 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1505 // blend on at multiple vertical offsets to achieve a vertical blur
1506 // TODO: do offset blends using GLSL
1507 range = r_bloom_blur.integer * bloomwidth / 320;
1508 GL_BlendFunc(GL_ONE, GL_ZERO);
1509 for (x = -range;x <= range;x++)
1511 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1512 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1513 // compute a texcoord array with the specified x and y offset
1514 varray_texcoord2f[2][0] = xoffset+0;
1515 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1516 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1517 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1518 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1519 varray_texcoord2f[2][5] = yoffset+0;
1520 varray_texcoord2f[2][6] = xoffset+0;
1521 varray_texcoord2f[2][7] = yoffset+0;
1522 // this r value looks like a 'dot' particle, fading sharply to
1523 // black at the edges
1524 // (probably not realistic but looks good enough)
1525 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1528 GL_Color(r, r, r, 1);
1529 R_Mesh_Draw(0, 4, 2, polygonelements);
1530 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1531 GL_BlendFunc(GL_ONE, GL_ONE);
1533 // copy the vertically blurred bloom view to a texture
1534 GL_ActiveTexture(0);
1535 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1536 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1537 // blend the vertically blurred image at multiple offsets horizontally
1538 // to finish the blur effect
1539 // TODO: do offset blends using GLSL
1540 range = r_bloom_blur.integer * bloomwidth / 320;
1541 GL_BlendFunc(GL_ONE, GL_ZERO);
1542 for (x = -range;x <= range;x++)
1544 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1545 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1546 // compute a texcoord array with the specified x and y offset
1547 varray_texcoord2f[2][0] = xoffset+0;
1548 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1549 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1550 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1551 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1552 varray_texcoord2f[2][5] = yoffset+0;
1553 varray_texcoord2f[2][6] = xoffset+0;
1554 varray_texcoord2f[2][7] = yoffset+0;
1555 // this r value looks like a 'dot' particle, fading sharply to
1556 // black at the edges
1557 // (probably not realistic but looks good enough)
1558 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1561 GL_Color(r, r, r, 1);
1562 R_Mesh_Draw(0, 4, 2, polygonelements);
1563 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1564 GL_BlendFunc(GL_ONE, GL_ONE);
1566 // copy the blurred bloom view to a texture
1567 GL_ActiveTexture(0);
1568 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1569 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1570 // go back to full view area
1571 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1572 // put the original screen image back in place and blend the bloom
1574 memset(&m, 0, sizeof(m));
1575 m.pointer_vertex = varray_vertex3f;
1576 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1577 m.pointer_texcoord[0] = varray_texcoord2f[0];
1579 dobloomblend = false;
1581 // do both in one pass if possible
1582 if (r_textureunits.integer >= 2 && gl_combine.integer)
1584 dobloomblend = false;
1585 m.texcombinergb[1] = GL_ADD;
1586 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1587 m.pointer_texcoord[1] = varray_texcoord2f[1];
1590 dobloomblend = true;
1593 GL_BlendFunc(GL_ONE, GL_ZERO);
1595 R_Mesh_Draw(0, 4, 2, polygonelements);
1596 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1597 // now blend on the bloom texture if multipass
1600 memset(&m, 0, sizeof(m));
1601 m.pointer_vertex = varray_vertex3f;
1602 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1603 m.pointer_texcoord[0] = varray_texcoord2f[1];
1605 GL_BlendFunc(GL_ONE, GL_ONE);
1607 R_Mesh_Draw(0, 4, 2, polygonelements);
1608 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1613 // apply a color tint to the whole view
1614 memset(&m, 0, sizeof(m));
1615 m.pointer_vertex = varray_vertex3f;
1617 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1618 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1619 R_Mesh_Draw(0, 4, 2, polygonelements);
1623 void R_RenderScene(void);
1625 matrix4x4_t r_waterscrollmatrix;
1632 void R_RenderView(void)
1634 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1635 return; //Host_Error ("R_RenderView: NULL worldmodel");
1637 r_view_width = bound(0, r_refdef.width, vid.width);
1638 r_view_height = bound(0, r_refdef.height, vid.height);
1640 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1641 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1643 r_view_matrix = r_refdef.viewentitymatrix;
1644 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1645 r_rtworld = r_shadow_realtime_world.integer;
1646 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1647 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1648 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1649 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1651 // GL is weird because it's bottom to top, r_view_y is top to bottom
1652 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1653 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1654 GL_ScissorTest(true);
1659 if (r_timereport_active)
1660 R_TimeReport("setup");
1662 qglDepthFunc(GL_LEQUAL);
1663 qglPolygonOffset(0, 0);
1664 qglEnable(GL_POLYGON_OFFSET_FILL);
1668 qglPolygonOffset(0, 0);
1669 qglDisable(GL_POLYGON_OFFSET_FILL);
1672 if (r_timereport_active)
1673 R_TimeReport("blendview");
1675 GL_Scissor(0, 0, vid.width, vid.height);
1676 GL_ScissorTest(false);
1680 void CSQC_R_ClearScreen (void)
1682 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1683 return; //Host_Error ("R_RenderView: NULL worldmodel");
1685 r_view_width = bound(0, r_refdef.width, vid.width);
1686 r_view_height = bound(0, r_refdef.height, vid.height);
1688 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1689 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1691 r_view_matrix = r_refdef.viewentitymatrix;
1692 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1693 r_rtworld = r_shadow_realtime_world.integer;
1694 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1695 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1696 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1697 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1699 // GL is weird because it's bottom to top, r_view_y is top to bottom
1700 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1701 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1702 GL_ScissorTest(true);
1707 if (r_timereport_active)
1708 R_TimeReport("setup");
1712 void CSQC_R_RenderScene (void)
1714 qglDepthFunc(GL_LEQUAL);
1715 qglPolygonOffset(0, 0);
1716 qglEnable(GL_POLYGON_OFFSET_FILL);
1720 qglPolygonOffset(0, 0);
1721 qglDisable(GL_POLYGON_OFFSET_FILL);
1724 if (r_timereport_active)
1725 R_TimeReport("blendview");
1727 GL_Scissor(0, 0, vid.width, vid.height);
1728 GL_ScissorTest(false);
1731 extern void R_DrawLightningBeams (void);
1732 extern void VM_AddPolygonsToMeshQueue (void);
1733 void R_RenderScene(void)
1737 // don't let sound skip if going slow
1738 if (r_refdef.extraupdate)
1743 if (gl_support_fragment_shader)
1744 qglUseProgramObjectARB(0);
1746 R_MeshQueue_BeginScene();
1750 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1751 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1753 if (r_rtworldshadows || r_rtdlightshadows)
1754 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1756 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1758 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1760 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);
1764 R_WorldVisibility();
1765 if (r_timereport_active)
1766 R_TimeReport("worldvis");
1769 if (r_timereport_active)
1770 R_TimeReport("markentity");
1772 R_Shadow_UpdateWorldLightSelection();
1774 for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1780 GL_BlendFunc(GL_ONE, GL_ONE);
1781 GL_DepthTest(!r_showdisabledepthtest.integer);
1782 GL_DepthMask(GL_FALSE);
1783 memset(&m, 0, sizeof(m));
1785 //qglEnable(GL_LINE_SMOOTH);
1786 qglEnable(GL_POLYGON_OFFSET_LINE);
1787 qglPolygonOffset(0, r_showtris_polygonoffset.value);
1791 if (cl.csqc_vidvars.drawworld)
1793 // don't let sound skip if going slow
1794 if (r_refdef.extraupdate)
1798 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1799 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1801 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1802 if (r_timereport_active)
1803 R_TimeReport("worldsky");
1806 if (R_DrawBrushModelsSky() && r_timereport_active)
1807 R_TimeReport("bmodelsky");
1810 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1811 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1813 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1814 if (r_timereport_active)
1815 R_TimeReport("world");
1819 // don't let sound skip if going slow
1820 if (r_refdef.extraupdate)
1824 GL_ShowTrisColor(0, 0.015, 0, 1);
1827 if (r_timereport_active)
1828 R_TimeReport("models");
1830 // don't let sound skip if going slow
1831 if (r_refdef.extraupdate)
1835 GL_ShowTrisColor(0, 0, 0.033, 1);
1836 R_ShadowVolumeLighting(false);
1837 if (r_timereport_active)
1838 R_TimeReport("rtlights");
1840 // don't let sound skip if going slow
1841 if (r_refdef.extraupdate)
1845 GL_ShowTrisColor(0.1, 0, 0, 1);
1847 if (cl.csqc_vidvars.drawworld)
1849 R_DrawLightningBeams();
1850 if (r_timereport_active)
1851 R_TimeReport("lightning");
1854 if (r_timereport_active)
1855 R_TimeReport("particles");
1858 if (r_timereport_active)
1859 R_TimeReport("explosions");
1862 R_MeshQueue_RenderTransparent();
1863 if (r_timereport_active)
1864 R_TimeReport("drawtrans");
1866 if (cl.csqc_vidvars.drawworld)
1869 if (r_timereport_active)
1870 R_TimeReport("coronas");
1872 if(cl.csqc_vidvars.drawcrosshair)
1874 R_DrawWorldCrosshair();
1875 if (r_timereport_active)
1876 R_TimeReport("crosshair");
1879 VM_AddPolygonsToMeshQueue();
1881 R_MeshQueue_Render();
1885 //qglDisable(GL_LINE_SMOOTH);
1886 qglDisable(GL_POLYGON_OFFSET_LINE);
1892 R_MeshQueue_EndScene();
1894 // don't let sound skip if going slow
1895 if (r_refdef.extraupdate)
1898 if (gl_support_fragment_shader)
1899 qglUseProgramObjectARB(0);
1903 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1906 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1908 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1909 GL_DepthMask(false);
1911 R_Mesh_Matrix(&identitymatrix);
1913 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1914 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1915 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1916 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1917 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1918 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1919 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1920 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1921 R_FillColors(color, 8, cr, cg, cb, ca);
1924 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1926 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1928 c[0] = c[0] * f1 + fogcolor[0] * f2;
1929 c[1] = c[1] * f1 + fogcolor[1] * f2;
1930 c[2] = c[2] * f1 + fogcolor[2] * f2;
1933 memset(&m, 0, sizeof(m));
1934 m.pointer_vertex = vertex3f;
1935 m.pointer_color = color;
1941 int nomodelelements[24] =
1953 float nomodelvertex3f[6*3] =
1963 float nomodelcolor4f[6*4] =
1965 0.0f, 0.0f, 0.5f, 1.0f,
1966 0.0f, 0.0f, 0.5f, 1.0f,
1967 0.0f, 0.5f, 0.0f, 1.0f,
1968 0.0f, 0.5f, 0.0f, 1.0f,
1969 0.5f, 0.0f, 0.0f, 1.0f,
1970 0.5f, 0.0f, 0.0f, 1.0f
1973 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
1979 R_Mesh_Matrix(&ent->matrix);
1981 memset(&m, 0, sizeof(m));
1982 m.pointer_vertex = nomodelvertex3f;
1984 if (ent->flags & EF_ADDITIVE)
1986 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1987 GL_DepthMask(false);
1989 else if (ent->alpha < 1)
1991 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1992 GL_DepthMask(false);
1996 GL_BlendFunc(GL_ONE, GL_ZERO);
1999 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2002 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2003 m.pointer_color = color4f;
2004 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2006 for (i = 0, c = color4f;i < 6;i++, c += 4)
2008 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2009 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2010 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2014 else if (ent->alpha != 1)
2016 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2017 m.pointer_color = color4f;
2018 for (i = 0, c = color4f;i < 6;i++, c += 4)
2022 m.pointer_color = nomodelcolor4f;
2024 R_Mesh_Draw(0, 6, 8, nomodelelements);
2027 void R_DrawNoModel(entity_render_t *ent)
2029 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2030 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2032 // R_DrawNoModelCallback(ent, 0);
2035 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2037 vec3_t right1, right2, diff, normal;
2039 VectorSubtract (org2, org1, normal);
2041 // calculate 'right' vector for start
2042 VectorSubtract (r_vieworigin, org1, diff);
2043 CrossProduct (normal, diff, right1);
2044 VectorNormalize (right1);
2046 // calculate 'right' vector for end
2047 VectorSubtract (r_vieworigin, org2, diff);
2048 CrossProduct (normal, diff, right2);
2049 VectorNormalize (right2);
2051 vert[ 0] = org1[0] + width * right1[0];
2052 vert[ 1] = org1[1] + width * right1[1];
2053 vert[ 2] = org1[2] + width * right1[2];
2054 vert[ 3] = org1[0] - width * right1[0];
2055 vert[ 4] = org1[1] - width * right1[1];
2056 vert[ 5] = org1[2] - width * right1[2];
2057 vert[ 6] = org2[0] - width * right2[0];
2058 vert[ 7] = org2[1] - width * right2[1];
2059 vert[ 8] = org2[2] - width * right2[2];
2060 vert[ 9] = org2[0] + width * right2[0];
2061 vert[10] = org2[1] + width * right2[1];
2062 vert[11] = org2[2] + width * right2[2];
2065 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2067 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)
2069 float fog = 0.0f, ifog;
2073 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2076 R_Mesh_Matrix(&identitymatrix);
2077 GL_BlendFunc(blendfunc1, blendfunc2);
2078 GL_DepthMask(false);
2079 GL_DepthTest(!depthdisable);
2081 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2082 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2083 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2084 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2085 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2086 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2087 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2088 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2089 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2090 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2091 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2092 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2094 memset(&m, 0, sizeof(m));
2095 m.tex[0] = R_GetTexture(texture);
2096 m.pointer_texcoord[0] = spritetexcoord2f;
2097 m.pointer_vertex = varray_vertex3f;
2099 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2100 R_Mesh_Draw(0, 4, 2, polygonelements);
2102 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2104 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2105 GL_BlendFunc(blendfunc1, GL_ONE);
2106 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2107 R_Mesh_Draw(0, 4, 2, polygonelements);
2111 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2115 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2116 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2118 if (i == mesh->numvertices)
2120 if (mesh->numvertices < mesh->maxvertices)
2122 VectorCopy(v, vertex3f);
2123 mesh->numvertices++;
2125 return mesh->numvertices;
2131 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2135 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2136 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2137 e = mesh->element3i + mesh->numtriangles * 3;
2138 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2140 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2141 if (mesh->numtriangles < mesh->maxtriangles)
2146 mesh->numtriangles++;
2148 element[1] = element[2];
2152 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2154 int planenum, planenum2;
2157 mplane_t *plane, *plane2;
2158 float temppoints[2][256*3];
2159 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2163 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2164 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2166 if (planenum2 == planenum)
2168 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);
2171 if (tempnumpoints < 3)
2173 // generate elements forming a triangle fan for this polygon
2174 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2178 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)
2180 texturelayer_t *layer;
2181 layer = t->currentlayers + t->currentnumlayers++;
2183 layer->depthmask = depthmask;
2184 layer->blendfunc1 = blendfunc1;
2185 layer->blendfunc2 = blendfunc2;
2186 layer->texture = texture;
2187 layer->texmatrix = *matrix;
2188 layer->color[0] = r;
2189 layer->color[1] = g;
2190 layer->color[2] = b;
2191 layer->color[3] = a;
2194 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2196 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2197 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2200 texture_t *texture = t;
2201 model_t *model = ent->model;
2202 int s = ent->skinnum;
2203 if ((unsigned int)s >= (unsigned int)model->numskins)
2205 if (model->skinscenes)
2207 if (model->skinscenes[s].framecount > 1)
2208 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2210 s = model->skinscenes[s].firstframe;
2213 t = t + s * model->num_surfaces;
2215 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];
2216 texture->currentframe = t;
2219 t->currentmaterialflags = t->basematerialflags;
2220 t->currentalpha = ent->alpha;
2221 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2222 t->currentalpha *= r_wateralpha.value;
2223 if (!(ent->flags & RENDER_LIGHT))
2224 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2225 if (ent->effects & EF_ADDITIVE)
2226 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2227 else if (t->currentalpha < 1)
2228 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2229 if (ent->effects & EF_NODEPTHTEST)
2230 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2231 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2232 t->currenttexmatrix = r_waterscrollmatrix;
2234 t->currenttexmatrix = identitymatrix;
2236 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2237 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2238 t->glosstexture = r_texture_white;
2239 t->specularpower = 8;
2240 t->specularscale = 0;
2241 if (r_shadow_gloss.integer > 0)
2245 if (r_shadow_glossintensity.value > 0)
2247 t->glosstexture = t->skin.gloss;
2248 t->specularscale = r_shadow_glossintensity.value;
2251 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2252 t->specularscale = r_shadow_gloss2intensity.value;
2255 t->currentnumlayers = 0;
2256 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2258 if (gl_lightmaps.integer)
2259 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2260 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2262 int blendfunc1, blendfunc2, depthmask;
2263 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2265 blendfunc1 = GL_SRC_ALPHA;
2266 blendfunc2 = GL_ONE;
2269 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2271 blendfunc1 = GL_SRC_ALPHA;
2272 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2277 blendfunc1 = GL_ONE;
2278 blendfunc2 = GL_ZERO;
2281 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2283 rtexture_t *currentbasetexture;
2285 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2286 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2287 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2288 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2290 // fullbright is not affected by r_lightmapintensity
2291 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2292 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2293 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);
2294 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2295 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);
2301 // q3bsp has no lightmap updates, so the lightstylevalue that
2302 // would normally be baked into the lightmaptexture must be
2303 // applied to the color
2304 if (ent->model->type == mod_brushq3)
2305 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2306 colorscale *= r_lightmapintensity;
2307 if (r_textureunits.integer >= 2 && gl_combine.integer)
2308 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);
2309 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2310 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);
2312 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);
2313 if (r_ambient.value >= (1.0f/64.0f))
2314 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);
2315 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2317 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);
2318 if (r_ambient.value >= (1.0f/64.0f))
2319 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);
2321 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2323 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);
2324 if (r_ambient.value >= (1.0f/64.0f))
2325 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);
2328 if (t->skin.glow != NULL)
2329 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2330 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2332 // if this is opaque use alpha blend which will darken the earlier
2335 // if this is an alpha blended material, all the earlier passes
2336 // were darkened by fog already, so we only need to add the fog
2337 // color ontop through the fog mask texture
2339 // if this is an additive blended material, all the earlier passes
2340 // were darkened by fog already, and we should not add fog color
2341 // (because the background was not darkened, there is no fog color
2342 // that was lost behind it).
2343 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);
2350 void R_UpdateAllTextureInfo(entity_render_t *ent)
2354 for (i = 0;i < ent->model->num_textures;i++)
2355 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2358 float *rsurface_vertex3f;
2359 float *rsurface_svector3f;
2360 float *rsurface_tvector3f;
2361 float *rsurface_normal3f;
2362 float *rsurface_lightmapcolor4f;
2364 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
2366 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
2368 rsurface_vertex3f = varray_vertex3f;
2369 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
2370 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2372 rsurface_svector3f = varray_svector3f;
2373 rsurface_tvector3f = varray_tvector3f;
2374 rsurface_normal3f = varray_normal3f;
2375 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);
2379 rsurface_svector3f = NULL;
2380 rsurface_tvector3f = NULL;
2381 if (generatenormals)
2383 rsurface_normal3f = varray_normal3f;
2384 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);
2387 rsurface_normal3f = NULL;
2392 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
2393 rsurface_svector3f = surface->groupmesh->data_svector3f;
2394 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
2395 rsurface_normal3f = surface->groupmesh->data_normal3f;
2397 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2400 float center[3], forward[3], right[3], up[3], v[4][3];
2401 matrix4x4_t matrix1, imatrix1;
2402 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
2403 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
2404 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
2405 // a single autosprite surface can contain multiple sprites...
2406 for (j = 0;j < surface->num_vertices - 3;j += 4)
2408 VectorClear(center);
2409 for (i = 0;i < 4;i++)
2410 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2411 VectorScale(center, 0.25f, center);
2412 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2413 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);
2414 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2415 for (i = 0;i < 4;i++)
2416 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2417 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2419 forward[0] = modelorg[0] - center[0];
2420 forward[1] = modelorg[1] - center[1];
2422 VectorNormalize(forward);
2423 right[0] = forward[1];
2424 right[1] = -forward[0];
2426 VectorSet(up, 0, 0, 1);
2428 for (i = 0;i < 4;i++)
2429 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
2431 rsurface_vertex3f = varray_vertex3f;
2432 rsurface_svector3f = varray_svector3f;
2433 rsurface_tvector3f = varray_tvector3f;
2434 rsurface_normal3f = varray_normal3f;
2435 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);
2437 R_Mesh_VertexPointer(rsurface_vertex3f);
2440 static void RSurf_Draw(const msurface_t *surface)
2442 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2443 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2444 GL_LockArrays(0, 0);
2447 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)
2452 RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode >= 2, false);
2456 vec4_t ambientcolor;
2457 vec3_t diffusecolor;
2459 VectorCopy(ent->modellight_lightdir, lightdir);
2460 ambientcolor[0] = ent->modellight_ambient[0] * r * 0.5f;
2461 ambientcolor[1] = ent->modellight_ambient[1] * g * 0.5f;
2462 ambientcolor[2] = ent->modellight_ambient[2] * b * 0.5f;
2463 diffusecolor[0] = ent->modellight_diffuse[0] * r * 0.5f;
2464 diffusecolor[1] = ent->modellight_diffuse[1] * g * 0.5f;
2465 diffusecolor[2] = ent->modellight_diffuse[2] * b * 0.5f;
2466 if (VectorLength2(diffusecolor) > 0)
2468 int numverts = surface->num_vertices;
2469 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2470 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2471 c = varray_color4f + 4 * surface->num_firstvertex;
2472 // q3-style directional shading
2473 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2475 if ((f = DotProduct(c2, lightdir)) > 0)
2477 VectorMA(ambientcolor, f, diffusecolor, c);
2481 VectorCopy4(ambientcolor, c);
2488 rsurface_lightmapcolor4f = varray_color4f;
2492 r = ambientcolor[0];
2493 g = ambientcolor[1];
2494 b = ambientcolor[2];
2495 rsurface_lightmapcolor4f = NULL;
2498 else if (lightmode >= 1)
2500 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2502 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2504 if (surface->lightmapinfo->samples)
2506 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
2507 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2508 VectorScale(lm, scale, c);
2509 if (surface->lightmapinfo->styles[1] != 255)
2511 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2513 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2514 VectorMA(c, scale, lm, c);
2515 if (surface->lightmapinfo->styles[2] != 255)
2518 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2519 VectorMA(c, scale, lm, c);
2520 if (surface->lightmapinfo->styles[3] != 255)
2523 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2524 VectorMA(c, scale, lm, c);
2532 rsurface_lightmapcolor4f = varray_color4f;
2535 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
2538 rsurface_lightmapcolor4f = NULL;
2541 if (rsurface_lightmapcolor4f)
2543 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)
2545 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2554 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)
2556 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2563 rsurface_lightmapcolor4f = varray_color4f;
2565 if (applycolor && rsurface_lightmapcolor4f)
2567 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)
2574 rsurface_lightmapcolor4f = varray_color4f;
2576 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2577 GL_Color(r, g, b, a);
2578 RSurf_Draw(surface);
2581 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2583 int texturesurfaceindex;
2585 const msurface_t *surface;
2586 qboolean applycolor;
2589 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2591 r_shadow_rtlight = NULL;
2592 renderstats.entities_surfaces += texturenumsurfaces;
2593 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2594 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2595 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2596 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2597 qglDisable(GL_CULL_FACE);
2598 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2600 // transparent sky would be ridiculous
2601 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2606 skyrendernow = false;
2607 if (skyrendermasked)
2610 // restore entity matrix and GL_Color
2611 R_Mesh_Matrix(&ent->matrix);
2615 // LordHavoc: HalfLife maps have freaky skypolys...
2616 //if (!ent->model->brush.ishlbsp)
2618 if (skyrendermasked)
2620 // depth-only (masking)
2621 GL_ColorMask(0,0,0,0);
2622 // just to make sure that braindead drivers don't draw anything
2623 // despite that colormask...
2624 GL_BlendFunc(GL_ZERO, GL_ONE);
2629 GL_BlendFunc(GL_ONE, GL_ZERO);
2631 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2632 memset(&m, 0, sizeof(m));
2634 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2636 surface = texturesurfacelist[texturesurfaceindex];
2637 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2638 RSurf_Draw(surface);
2640 if (skyrendermasked)
2641 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2645 else if (r_glsl.integer && gl_support_fragment_shader)
2647 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2649 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2650 GL_DepthMask(false);
2652 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2654 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2655 GL_DepthMask(false);
2659 GL_BlendFunc(GL_ONE, GL_ZERO);
2663 memset(&m, 0, sizeof(m));
2665 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2666 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2667 if (!r_glsl_permutation)
2671 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2673 surface = texturesurfacelist[texturesurfaceindex];
2674 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2675 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2676 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2677 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2678 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2679 RSurf_Draw(surface);
2684 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2686 surface = texturesurfacelist[texturesurfaceindex];
2687 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2688 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2689 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2690 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2691 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2692 R_Mesh_TexCoordPointer(4, 2, surface->groupmesh->data_texcoordlightmap2f);
2693 if (surface->lightmaptexture)
2695 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2696 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2697 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2698 //R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2699 R_Mesh_ColorPointer(NULL);
2703 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2704 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2705 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2706 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2708 RSurf_Draw(surface);
2711 qglUseProgramObjectARB(0);
2713 else if (texture->currentnumlayers)
2716 texturelayer_t *layer;
2717 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2720 int layertexrgbscale;
2721 GL_DepthMask(layer->depthmask);
2722 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2723 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2725 layertexrgbscale = 4;
2726 VectorScale(layer->color, 0.25f, layercolor);
2728 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2730 layertexrgbscale = 2;
2731 VectorScale(layer->color, 0.5f, layercolor);
2735 layertexrgbscale = 1;
2736 VectorScale(layer->color, 1.0f, layercolor);
2738 layercolor[3] = layer->color[3];
2739 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2740 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2741 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2742 switch (layer->type)
2744 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2745 memset(&m, 0, sizeof(m));
2746 m.tex[1] = R_GetTexture(layer->texture);
2747 m.texmatrix[1] = layer->texmatrix;
2748 m.texrgbscale[1] = layertexrgbscale;
2749 m.pointer_color = varray_color4f;
2753 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2755 surface = texturesurfacelist[texturesurfaceindex];
2756 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2757 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2758 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2759 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2764 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2766 surface = texturesurfacelist[texturesurfaceindex];
2767 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2768 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2769 if (surface->lightmaptexture)
2771 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2772 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2776 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2777 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2782 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2783 memset(&m, 0, sizeof(m));
2784 m.tex[0] = R_GetTexture(layer->texture);
2785 m.texmatrix[0] = layer->texmatrix;
2786 m.pointer_color = varray_color4f;
2787 m.texrgbscale[0] = layertexrgbscale;
2791 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2793 surface = texturesurfacelist[texturesurfaceindex];
2794 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2795 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2796 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2801 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2803 surface = texturesurfacelist[texturesurfaceindex];
2804 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2805 if (surface->lightmaptexture)
2807 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2808 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
2812 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2813 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2817 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2818 memset(&m, 0, sizeof(m));
2819 m.tex[0] = R_GetTexture(layer->texture);
2820 m.texmatrix[0] = layer->texmatrix;
2821 m.pointer_color = varray_color4f;
2822 m.texrgbscale[0] = layertexrgbscale;
2824 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2826 surface = texturesurfacelist[texturesurfaceindex];
2827 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2828 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2831 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2832 memset(&m, 0, sizeof(m));
2833 m.tex[0] = R_GetTexture(layer->texture);
2834 m.texmatrix[0] = layer->texmatrix;
2835 m.texrgbscale[0] = layertexrgbscale;
2836 m.pointer_color = varray_color4f;
2840 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2842 surface = texturesurfacelist[texturesurfaceindex];
2843 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2844 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2849 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2851 surface = texturesurfacelist[texturesurfaceindex];
2852 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2853 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2857 case TEXTURELAYERTYPE_TEXTURE:
2858 memset(&m, 0, sizeof(m));
2859 m.tex[0] = R_GetTexture(layer->texture);
2860 m.texmatrix[0] = layer->texmatrix;
2861 m.pointer_color = varray_color4f;
2862 m.texrgbscale[0] = layertexrgbscale;
2864 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2866 surface = texturesurfacelist[texturesurfaceindex];
2867 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2868 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2871 case TEXTURELAYERTYPE_FOG:
2872 memset(&m, 0, sizeof(m));
2875 m.tex[0] = R_GetTexture(layer->texture);
2876 m.texmatrix[0] = layer->texmatrix;
2879 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2883 surface = texturesurfacelist[texturesurfaceindex];
2884 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2886 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2887 R_Mesh_ColorPointer(varray_color4f);
2888 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)
2890 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2891 c[0] = layercolor[0];
2892 c[1] = layercolor[1];
2893 c[2] = layercolor[2];
2894 c[3] = f * layercolor[3];
2896 RSurf_Draw(surface);
2900 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2902 // if trying to do overbright on first pass of an opaque surface
2903 // when combine is not supported, brighten as a post process
2904 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2907 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2908 GL_Color(1, 1, 1, 1);
2909 memset(&m, 0, sizeof(m));
2911 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2913 surface = texturesurfacelist[texturesurfaceindex];
2914 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2915 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2916 RSurf_Draw(surface);
2920 if (r_shownormals.integer && !r_showtrispass)
2924 GL_DepthTest(!r_showdisabledepthtest.integer);
2925 GL_DepthMask(texture->currentlayers->depthmask);
2926 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
2927 memset(&m, 0, sizeof(m));
2929 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2931 surface = texturesurfacelist[texturesurfaceindex];
2932 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2933 GL_Color(1, 0, 0, 1);
2935 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2937 VectorCopy(rsurface_vertex3f + k * 3, v);
2938 qglVertex3f(v[0], v[1], v[2]);
2939 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
2940 qglVertex3f(v[0], v[1], v[2]);
2942 GL_Color(0, 0, 1, 1);
2943 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2945 VectorCopy(rsurface_vertex3f + k * 3, v);
2946 qglVertex3f(v[0], v[1], v[2]);
2947 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
2948 qglVertex3f(v[0], v[1], v[2]);
2950 GL_Color(0, 1, 0, 1);
2951 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2953 VectorCopy(rsurface_vertex3f + k * 3, v);
2954 qglVertex3f(v[0], v[1], v[2]);
2955 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
2956 qglVertex3f(v[0], v[1], v[2]);
2962 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2963 qglEnable(GL_CULL_FACE);
2966 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2968 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
2972 texture = surface->texture;
2973 if (texture->basematerialflags & MATERIALFLAG_SKY)
2974 return; // transparent sky is too difficult
2975 R_UpdateTextureInfo(ent, texture);
2977 R_Mesh_Matrix(&ent->matrix);
2978 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2979 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2982 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2984 int texturesurfaceindex;
2985 const msurface_t *surface;
2986 vec3_t tempcenter, center;
2987 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2989 // drawing sky transparently would be too difficult
2990 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2992 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2994 surface = texturesurfacelist[texturesurfaceindex];
2995 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2996 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2997 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2998 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2999 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3004 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3007 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3008 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3010 int i, j, f, flagsmask;
3011 int counttriangles = 0;
3012 msurface_t *surface, **surfacechain;
3013 texture_t *t, *texture;
3014 model_t *model = ent->model;
3016 const int maxsurfacelist = 1024;
3017 int numsurfacelist = 0;
3018 const msurface_t *surfacelist[1024];
3021 R_Mesh_Matrix(&ent->matrix);
3022 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3024 // update light styles
3025 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3027 for (i = 0;i < model->brushq1.light_styles;i++)
3029 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3031 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3032 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3033 for (;(surface = *surfacechain);surfacechain++)
3034 surface->cached_dlight = true;
3039 R_UpdateAllTextureInfo(ent);
3040 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3045 if (ent == r_refdef.worldentity)
3047 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3049 if (!r_worldsurfacevisible[j])
3051 if (t != surface->texture)
3055 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3058 t = surface->texture;
3059 texture = t->currentframe;
3060 f = texture->currentmaterialflags & flagsmask;
3062 if (f && surface->num_triangles)
3064 // if lightmap parameters changed, rebuild lightmap texture
3065 if (surface->cached_dlight)
3066 R_BuildLightMap(ent, surface);
3067 // add face to draw list
3068 surfacelist[numsurfacelist++] = surface;
3069 counttriangles += surface->num_triangles;
3070 if (numsurfacelist >= maxsurfacelist)
3072 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3080 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3082 if (t != surface->texture)
3086 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3089 t = surface->texture;
3090 texture = t->currentframe;
3091 f = texture->currentmaterialflags & flagsmask;
3093 if (f && surface->num_triangles)
3095 // if lightmap parameters changed, rebuild lightmap texture
3096 if (surface->cached_dlight)
3097 R_BuildLightMap(ent, surface);
3098 // add face to draw list
3099 surfacelist[numsurfacelist++] = surface;
3100 counttriangles += surface->num_triangles;
3101 if (numsurfacelist >= maxsurfacelist)
3103 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3110 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3111 if (!r_showtrispass)
3112 renderstats.entities_triangles += counttriangles;
3113 if (gl_support_fragment_shader)
3114 qglUseProgramObjectARB(0);