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_DELUXEMAPPING)
661 vertstrings_list[vertstrings_count++] = "#define USEDELUXEMAP\n";
662 fragstrings_list[fragstrings_count++] = "#define USEDELUXEMAP\n";
663 strlcat(permutationname, " deluxemap", sizeof(permutationname));
665 if (permutation & SHADERPERMUTATION_LIGHTSOURCE)
667 vertstrings_list[vertstrings_count++] = "#define USELIGHTSOURCE\n";
668 fragstrings_list[fragstrings_count++] = "#define USELIGHTSOURCE\n";
669 strlcat(permutationname, " lightsource", sizeof(permutationname));
671 if (permutation & SHADERPERMUTATION_COLORMAPPING)
673 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
674 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
675 strlcat(permutationname, " colormapping", sizeof(permutationname));
677 if (permutation & SHADERPERMUTATION_SPECULAR)
679 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
680 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
681 strlcat(permutationname, " specular", sizeof(permutationname));
683 if (permutation & SHADERPERMUTATION_FOG)
685 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
686 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
687 strlcat(permutationname, " fog", sizeof(permutationname));
689 if (permutation & SHADERPERMUTATION_CUBEFILTER)
691 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
692 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
693 strlcat(permutationname, " cubefilter", sizeof(permutationname));
695 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
697 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
698 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
699 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
701 if (permutation & SHADERPERMUTATION_SURFACENORMALIZE)
703 vertstrings_list[vertstrings_count++] = "#define SURFACENORMALIZE\n";
704 fragstrings_list[fragstrings_count++] = "#define SURFACENORMALIZE\n";
705 strlcat(permutationname, " surfacenormalize", sizeof(permutationname));
707 if (permutation & SHADERPERMUTATION_GEFORCEFX)
709 vertstrings_list[vertstrings_count++] = "#define GEFORCEFX\n";
710 fragstrings_list[fragstrings_count++] = "#define GEFORCEFX\n";
711 strlcat(permutationname, " halffloat", sizeof(permutationname));
715 vertstrings_list[vertstrings_count++] = shaderstring;
716 fragstrings_list[fragstrings_count++] = shaderstring;
720 vertstrings_list[vertstrings_count++] = builtinshaderstring;
721 fragstrings_list[fragstrings_count++] = builtinshaderstring;
723 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
727 qglUseProgramObjectARB(p->program);
728 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
729 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
730 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
731 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
732 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
733 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
734 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
735 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
736 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
737 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
738 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
739 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
740 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
741 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
742 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
743 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
744 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
745 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
746 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
747 p->loc_OffsetMapping_Bias = qglGetUniformLocationARB(p->program, "OffsetMapping_Bias");
748 if (p->loc_Texture_Normal) qglUniform1iARB(p->loc_Texture_Normal, 0);
749 if (p->loc_Texture_Color) qglUniform1iARB(p->loc_Texture_Color, 1);
750 if (p->loc_Texture_Gloss) qglUniform1iARB(p->loc_Texture_Gloss, 2);
751 if (p->loc_Texture_Cube) qglUniform1iARB(p->loc_Texture_Cube, 3);
752 if (p->loc_Texture_FogMask) qglUniform1iARB(p->loc_Texture_FogMask, 4);
753 if (p->loc_Texture_Pants) qglUniform1iARB(p->loc_Texture_Pants, 5);
754 if (p->loc_Texture_Shirt) qglUniform1iARB(p->loc_Texture_Shirt, 6);
755 if (p->loc_Texture_Lightmap) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
756 if (p->loc_Texture_Deluxemap) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
757 qglUseProgramObjectARB(0);
761 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
764 void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t lightcolorbase, const vec3_t lightcolorpants, const vec3_t lightcolorshirt, rtexture_t *basetexture, rtexture_t *pantstexture, rtexture_t *shirttexture, rtexture_t *normalmaptexture, rtexture_t *glosstexture, float specularscale, qboolean dopants, qboolean doshirt)
766 // select a permutation of the lighting shader appropriate to this
767 // combination of texture, entity, light source, and fogging, only use the
768 // minimum features necessary to avoid wasting rendering time in the
769 // fragment shader on features that are not being used
771 r_glsl_permutation = NULL;
772 if (r_shadow_rtlight)
773 permutation |= SHADERPERMUTATION_LIGHTSOURCE;
775 permutation |= SHADERPERMUTATION_DELUXEMAPPING;
777 permutation |= SHADERPERMUTATION_FOG;
778 if ((dopants || doshirt))
779 permutation |= SHADERPERMUTATION_COLORMAPPING;
780 if (specularscale > 0)
781 permutation |= SHADERPERMUTATION_SPECULAR;
782 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
783 permutation |= SHADERPERMUTATION_CUBEFILTER;
784 if (r_glsl_offsetmapping.integer)
785 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
786 if (r_glsl_surfacenormalize.integer)
787 permutation |= SHADERPERMUTATION_SURFACENORMALIZE;
788 if (r_glsl_usehalffloat.integer)
789 permutation |= SHADERPERMUTATION_GEFORCEFX;
790 if (!r_glsl_permutations[permutation].program)
792 if (!r_glsl_permutations[permutation].compiled)
793 R_GLSL_CompilePermutation(permutation);
794 if (!r_glsl_permutations[permutation].program)
796 // remove features until we find a valid permutation
798 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
800 // reduce i more quickly whenever it would not remove any bits
804 if (!r_glsl_permutations[permutation].compiled)
805 R_GLSL_CompilePermutation(permutation);
806 if (r_glsl_permutations[permutation].program)
809 return; // utterly failed
813 r_glsl_permutation = r_glsl_permutations + permutation;
815 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
816 R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
817 if (r_shadow_rtlight)
818 R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
819 if (r_glsl_permutation->loc_Texture_Normal) R_Mesh_TexBind(0, R_GetTexture(normalmaptexture));
820 if (r_glsl_permutation->loc_Texture_Color) R_Mesh_TexBind(1, R_GetTexture(basetexture));
821 if (r_glsl_permutation->loc_FogColor)
823 // additive passes are only darkened by fog, not tinted
824 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
825 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
827 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
829 if (r_glsl_permutation->loc_LightPosition) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);
830 if (r_glsl_permutation->loc_EyePosition) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, r_shadow_entityeyeorigin[0], r_shadow_entityeyeorigin[1], r_shadow_entityeyeorigin[2]);
831 if (r_glsl_permutation->loc_LightColor) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
832 if (r_glsl_permutation->loc_Texture_Pants) R_Mesh_TexBind(5, R_GetTexture(pantstexture));
833 if (r_glsl_permutation->loc_Texture_Shirt) R_Mesh_TexBind(6, R_GetTexture(shirttexture));
834 if (r_glsl_permutation->loc_Color_Pants) qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
835 if (r_glsl_permutation->loc_Color_Shirt) qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
836 if (r_glsl_permutation->loc_FogRangeRecip) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
837 if (r_glsl_permutation->loc_AmbientScale) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
838 if (r_glsl_permutation->loc_DiffuseScale) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
839 if (r_glsl_permutation->loc_Texture_Gloss) R_Mesh_TexBind(2, R_GetTexture(glosstexture));
840 if (r_glsl_permutation->loc_SpecularPower) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, 8);
841 if (r_glsl_permutation->loc_SpecularScale) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
842 if (r_glsl_permutation->loc_OffsetMapping_Scale) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
843 if (r_glsl_permutation->loc_OffsetMapping_Bias) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Bias, r_glsl_offsetmapping_bias.value);
847 void gl_main_start(void)
849 // use half float math where available (speed gain on NVIDIA GFFX and GF6)
850 if (gl_support_half_float)
851 Cvar_SetValue("r_glsl_usehalffloat", 1);
852 r_main_texturepool = R_AllocTexturePool();
853 r_bloom_texture_screen = NULL;
854 r_bloom_texture_bloom = NULL;
855 R_BuildBlankTextures();
857 if (gl_texturecubemap)
860 R_BuildNormalizationCube();
864 if (gl_support_fragment_shader)
866 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
868 Con_Printf("GLSL shader text loaded from disk\n");
869 // if we couldn't load the shader file, fall back to builtin shader
873 Con_Printf("GLSL shader text loaded from fallback\n");
874 shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
875 strcpy(shaderstring, builtinshaderstring);
879 Con_Printf("GLSL shader text loaded\n");
880 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
883 void gl_main_shutdown(void)
886 R_FreeTexturePool(&r_main_texturepool);
887 r_bloom_texture_screen = NULL;
888 r_bloom_texture_bloom = NULL;
889 r_texture_blanknormalmap = NULL;
890 r_texture_white = NULL;
891 r_texture_black = NULL;
892 r_texture_whitecube = NULL;
893 r_texture_normalizationcube = NULL;
895 Mem_Free(shaderstring);
897 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
898 if (r_glsl_permutations[i].program)
899 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
900 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
903 extern void CL_ParseEntityLump(char *entitystring);
904 void gl_main_newmap(void)
906 // FIXME: move this code to client
908 char *entities, entname[MAX_QPATH];
912 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
913 l = (int)strlen(entname) - 4;
914 if (l >= 0 && !strcmp(entname + l, ".bsp"))
916 strcpy(entname + l, ".ent");
917 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
919 CL_ParseEntityLump(entities);
924 if (cl.worldmodel->brush.entities)
925 CL_ParseEntityLump(cl.worldmodel->brush.entities);
929 void GL_Main_Init(void)
931 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
933 FOG_registercvars(); // FIXME: move this fog stuff to client?
934 Cvar_RegisterVariable(&r_nearclip);
935 Cvar_RegisterVariable(&r_showtris);
936 Cvar_RegisterVariable(&r_showtris_polygonoffset);
937 Cvar_RegisterVariable(&r_shownormals);
938 Cvar_RegisterVariable(&r_showlighting);
939 Cvar_RegisterVariable(&r_showshadowvolumes);
940 Cvar_RegisterVariable(&r_showcollisionbrushes);
941 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
942 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
943 Cvar_RegisterVariable(&r_showdisabledepthtest);
944 Cvar_RegisterVariable(&r_drawentities);
945 Cvar_RegisterVariable(&r_drawviewmodel);
946 Cvar_RegisterVariable(&r_speeds);
947 Cvar_RegisterVariable(&r_fullbrights);
948 Cvar_RegisterVariable(&r_wateralpha);
949 Cvar_RegisterVariable(&r_dynamic);
950 Cvar_RegisterVariable(&r_fullbright);
951 Cvar_RegisterVariable(&r_textureunits);
952 Cvar_RegisterVariable(&r_glsl);
953 Cvar_RegisterVariable(&r_glsl_offsetmapping);
954 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
955 Cvar_RegisterVariable(&r_glsl_offsetmapping_bias);
956 Cvar_RegisterVariable(&r_glsl_usehalffloat);
957 Cvar_RegisterVariable(&r_glsl_surfacenormalize);
958 Cvar_RegisterVariable(&r_lerpsprites);
959 Cvar_RegisterVariable(&r_lerpmodels);
960 Cvar_RegisterVariable(&r_waterscroll);
961 Cvar_RegisterVariable(&r_bloom);
962 Cvar_RegisterVariable(&r_bloom_intensity);
963 Cvar_RegisterVariable(&r_bloom_blur);
964 Cvar_RegisterVariable(&r_bloom_resolution);
965 Cvar_RegisterVariable(&r_bloom_power);
966 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
967 Cvar_RegisterVariable(&developer_texturelogging);
968 Cvar_RegisterVariable(&gl_lightmaps);
969 Cvar_RegisterVariable(&r_test);
970 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
971 Cvar_SetValue("r_fullbrights", 0);
972 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
975 static vec3_t r_farclip_origin;
976 static vec3_t r_farclip_direction;
977 static vec_t r_farclip_directiondist;
978 static vec_t r_farclip_meshfarclip;
979 static int r_farclip_directionbit0;
980 static int r_farclip_directionbit1;
981 static int r_farclip_directionbit2;
983 // enlarge farclip to accomodate box
984 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
987 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
988 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
989 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
990 if (r_farclip_meshfarclip < d)
991 r_farclip_meshfarclip = d;
994 // return farclip value
995 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
999 VectorCopy(origin, r_farclip_origin);
1000 VectorCopy(direction, r_farclip_direction);
1001 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1002 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1003 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1004 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1005 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1007 if (r_refdef.worldmodel)
1008 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1009 for (i = 0;i < r_refdef.numentities;i++)
1010 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1012 return r_farclip_meshfarclip - r_farclip_directiondist;
1015 extern void R_Textures_Init(void);
1016 extern void GL_Draw_Init(void);
1017 extern void GL_Main_Init(void);
1018 extern void R_Shadow_Init(void);
1019 extern void R_Sky_Init(void);
1020 extern void GL_Surf_Init(void);
1021 extern void R_Crosshairs_Init(void);
1022 extern void R_Light_Init(void);
1023 extern void R_Particles_Init(void);
1024 extern void R_Explosion_Init(void);
1025 extern void gl_backend_init(void);
1026 extern void Sbar_Init(void);
1027 extern void R_LightningBeams_Init(void);
1028 extern void Mod_RenderInit(void);
1030 void Render_Init(void)
1040 R_Crosshairs_Init();
1045 R_LightningBeams_Init();
1054 extern char *ENGINE_EXTENSIONS;
1057 VID_CheckExtensions();
1059 // LordHavoc: report supported extensions
1060 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1062 // clear to black (loading plaque will be seen over this)
1063 qglClearColor(0,0,0,1);
1064 qglClear(GL_COLOR_BUFFER_BIT);
1067 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1071 for (i = 0;i < 4;i++)
1078 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1082 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1086 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1090 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1094 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1098 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1102 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1106 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1114 //==================================================================================
1116 static void R_MarkEntities (void)
1119 entity_render_t *ent;
1121 if (!r_drawentities.integer)
1124 r_refdef.worldentity->visframe = r_framecount;
1125 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1126 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1128 // worldmodel can check visibility
1129 for (i = 0;i < r_refdef.numentities;i++)
1131 ent = r_refdef.entities[i];
1132 // some of the renderer still relies on origin...
1133 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1134 // some of the renderer still relies on scale...
1135 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1136 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)))
1138 R_UpdateEntLights(ent);
1139 ent->visframe = r_framecount;
1145 // no worldmodel or it can't check visibility
1146 for (i = 0;i < r_refdef.numentities;i++)
1148 ent = r_refdef.entities[i];
1149 // some of the renderer still relies on origin...
1150 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1151 // some of the renderer still relies on scale...
1152 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1153 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1155 R_UpdateEntLights(ent);
1156 ent->visframe = r_framecount;
1162 // only used if skyrendermasked, and normally returns false
1163 int R_DrawBrushModelsSky (void)
1166 entity_render_t *ent;
1168 if (!r_drawentities.integer)
1172 for (i = 0;i < r_refdef.numentities;i++)
1174 ent = r_refdef.entities[i];
1175 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1177 ent->model->DrawSky(ent);
1184 void R_DrawNoModel(entity_render_t *ent);
1185 void R_DrawModels(void)
1188 entity_render_t *ent;
1190 if (!r_drawentities.integer)
1193 for (i = 0;i < r_refdef.numentities;i++)
1195 ent = r_refdef.entities[i];
1196 if (ent->visframe == r_framecount)
1198 renderstats.entities++;
1199 if (ent->model && ent->model->Draw != NULL)
1200 ent->model->Draw(ent);
1207 static void R_SetFrustum(void)
1209 // break apart the view matrix into vectors for various purposes
1210 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1211 VectorNegate(r_viewleft, r_viewright);
1214 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1215 frustum[0].normal[1] = 0 - 0;
1216 frustum[0].normal[2] = -1 - 0;
1217 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1218 frustum[1].normal[1] = 0 + 0;
1219 frustum[1].normal[2] = -1 + 0;
1220 frustum[2].normal[0] = 0 - 0;
1221 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1222 frustum[2].normal[2] = -1 - 0;
1223 frustum[3].normal[0] = 0 + 0;
1224 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1225 frustum[3].normal[2] = -1 + 0;
1229 zNear = r_nearclip.value;
1230 nudge = 1.0 - 1.0 / (1<<23);
1231 frustum[4].normal[0] = 0 - 0;
1232 frustum[4].normal[1] = 0 - 0;
1233 frustum[4].normal[2] = -1 - -nudge;
1234 frustum[4].dist = 0 - -2 * zNear * nudge;
1235 frustum[5].normal[0] = 0 + 0;
1236 frustum[5].normal[1] = 0 + 0;
1237 frustum[5].normal[2] = -1 + -nudge;
1238 frustum[5].dist = 0 + -2 * zNear * nudge;
1244 frustum[0].normal[0] = m[3] - m[0];
1245 frustum[0].normal[1] = m[7] - m[4];
1246 frustum[0].normal[2] = m[11] - m[8];
1247 frustum[0].dist = m[15] - m[12];
1249 frustum[1].normal[0] = m[3] + m[0];
1250 frustum[1].normal[1] = m[7] + m[4];
1251 frustum[1].normal[2] = m[11] + m[8];
1252 frustum[1].dist = m[15] + m[12];
1254 frustum[2].normal[0] = m[3] - m[1];
1255 frustum[2].normal[1] = m[7] - m[5];
1256 frustum[2].normal[2] = m[11] - m[9];
1257 frustum[2].dist = m[15] - m[13];
1259 frustum[3].normal[0] = m[3] + m[1];
1260 frustum[3].normal[1] = m[7] + m[5];
1261 frustum[3].normal[2] = m[11] + m[9];
1262 frustum[3].dist = m[15] + m[13];
1264 frustum[4].normal[0] = m[3] - m[2];
1265 frustum[4].normal[1] = m[7] - m[6];
1266 frustum[4].normal[2] = m[11] - m[10];
1267 frustum[4].dist = m[15] - m[14];
1269 frustum[5].normal[0] = m[3] + m[2];
1270 frustum[5].normal[1] = m[7] + m[6];
1271 frustum[5].normal[2] = m[11] + m[10];
1272 frustum[5].dist = m[15] + m[14];
1277 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1278 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1279 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1280 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1281 VectorCopy(r_viewforward, frustum[4].normal);
1282 VectorNormalize(frustum[0].normal);
1283 VectorNormalize(frustum[1].normal);
1284 VectorNormalize(frustum[2].normal);
1285 VectorNormalize(frustum[3].normal);
1286 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1287 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1288 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1289 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1290 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1291 PlaneClassify(&frustum[0]);
1292 PlaneClassify(&frustum[1]);
1293 PlaneClassify(&frustum[2]);
1294 PlaneClassify(&frustum[3]);
1295 PlaneClassify(&frustum[4]);
1297 // LordHavoc: note to all quake engine coders, Quake had a special case
1298 // for 90 degrees which assumed a square view (wrong), so I removed it,
1299 // Quake2 has it disabled as well.
1301 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1302 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1303 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1304 //PlaneClassify(&frustum[0]);
1306 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1307 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1308 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1309 //PlaneClassify(&frustum[1]);
1311 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1312 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1313 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1314 //PlaneClassify(&frustum[2]);
1316 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1317 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1318 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1319 //PlaneClassify(&frustum[3]);
1322 //VectorCopy(r_viewforward, frustum[4].normal);
1323 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1324 //PlaneClassify(&frustum[4]);
1327 static void R_BlendView(void)
1329 int screenwidth, screenheight;
1334 // set the (poorly named) screenwidth and screenheight variables to
1335 // a power of 2 at least as large as the screen, these will define the
1336 // size of the texture to allocate
1337 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1338 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1340 doblend = r_refdef.viewblend[3] >= 0.01f;
1341 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;
1343 if (!dobloom && !doblend)
1346 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1348 GL_DepthTest(false);
1349 R_Mesh_Matrix(&identitymatrix);
1350 // vertex coordinates for a quad that covers the screen exactly
1351 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
1352 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
1353 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
1354 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
1357 int bloomwidth, bloomheight, x, dobloomblend, range;
1358 float xoffset, yoffset, r;
1359 renderstats.bloom++;
1360 // allocate textures as needed
1361 if (!r_bloom_texture_screen)
1362 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1363 if (!r_bloom_texture_bloom)
1364 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1365 // set bloomwidth and bloomheight to the bloom resolution that will be
1366 // used (often less than the screen resolution for faster rendering)
1367 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1368 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1369 // set up a texcoord array for the full resolution screen image
1370 // (we have to keep this around to copy back during final render)
1371 varray_texcoord2f[0][0] = 0;
1372 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1373 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1374 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1375 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1376 varray_texcoord2f[0][5] = 0;
1377 varray_texcoord2f[0][6] = 0;
1378 varray_texcoord2f[0][7] = 0;
1379 // set up a texcoord array for the reduced resolution bloom image
1380 // (which will be additive blended over the screen image)
1381 varray_texcoord2f[1][0] = 0;
1382 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1383 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1384 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1385 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1386 varray_texcoord2f[1][5] = 0;
1387 varray_texcoord2f[1][6] = 0;
1388 varray_texcoord2f[1][7] = 0;
1389 memset(&m, 0, sizeof(m));
1390 m.pointer_vertex = varray_vertex3f;
1391 m.pointer_texcoord[0] = varray_texcoord2f[0];
1392 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1394 // copy view into the full resolution screen image texture
1395 GL_ActiveTexture(0);
1396 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1397 renderstats.bloom_copypixels += r_view_width * r_view_height;
1398 // now scale it down to the bloom size and raise to a power of itself
1399 // to darken it (this leaves the really bright stuff bright, and
1400 // everything else becomes very dark)
1401 // TODO: optimize with multitexture or GLSL
1402 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1403 GL_BlendFunc(GL_ONE, GL_ZERO);
1404 GL_Color(1, 1, 1, 1);
1405 R_Mesh_Draw(0, 4, 2, polygonelements);
1406 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1407 // render multiple times with a multiply blendfunc to raise to a power
1408 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1409 for (x = 1;x < r_bloom_power.integer;x++)
1411 R_Mesh_Draw(0, 4, 2, polygonelements);
1412 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1414 // we now have a darkened bloom image in the framebuffer, copy it into
1415 // the bloom image texture for more processing
1416 memset(&m, 0, sizeof(m));
1417 m.pointer_vertex = varray_vertex3f;
1418 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1419 m.pointer_texcoord[0] = varray_texcoord2f[2];
1421 GL_ActiveTexture(0);
1422 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1423 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1424 // blend on at multiple vertical offsets to achieve a vertical blur
1425 // TODO: do offset blends using GLSL
1426 range = r_bloom_blur.integer * bloomwidth / 320;
1427 GL_BlendFunc(GL_ONE, GL_ZERO);
1428 for (x = -range;x <= range;x++)
1430 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1431 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1432 // compute a texcoord array with the specified x and y offset
1433 varray_texcoord2f[2][0] = xoffset+0;
1434 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1435 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1436 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1437 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1438 varray_texcoord2f[2][5] = yoffset+0;
1439 varray_texcoord2f[2][6] = xoffset+0;
1440 varray_texcoord2f[2][7] = yoffset+0;
1441 // this r value looks like a 'dot' particle, fading sharply to
1442 // black at the edges
1443 // (probably not realistic but looks good enough)
1444 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1447 GL_Color(r, r, r, 1);
1448 R_Mesh_Draw(0, 4, 2, polygonelements);
1449 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1450 GL_BlendFunc(GL_ONE, GL_ONE);
1452 // copy the vertically blurred bloom view to a texture
1453 GL_ActiveTexture(0);
1454 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1455 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1456 // blend the vertically blurred image at multiple offsets horizontally
1457 // to finish the blur effect
1458 // TODO: do offset blends using GLSL
1459 range = r_bloom_blur.integer * bloomwidth / 320;
1460 GL_BlendFunc(GL_ONE, GL_ZERO);
1461 for (x = -range;x <= range;x++)
1463 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1464 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1465 // compute a texcoord array with the specified x and y offset
1466 varray_texcoord2f[2][0] = xoffset+0;
1467 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1468 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1469 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1470 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1471 varray_texcoord2f[2][5] = yoffset+0;
1472 varray_texcoord2f[2][6] = xoffset+0;
1473 varray_texcoord2f[2][7] = yoffset+0;
1474 // this r value looks like a 'dot' particle, fading sharply to
1475 // black at the edges
1476 // (probably not realistic but looks good enough)
1477 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1480 GL_Color(r, r, r, 1);
1481 R_Mesh_Draw(0, 4, 2, polygonelements);
1482 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1483 GL_BlendFunc(GL_ONE, GL_ONE);
1485 // copy the blurred bloom view to a texture
1486 GL_ActiveTexture(0);
1487 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1488 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1489 // go back to full view area
1490 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1491 // put the original screen image back in place and blend the bloom
1493 memset(&m, 0, sizeof(m));
1494 m.pointer_vertex = varray_vertex3f;
1495 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1496 m.pointer_texcoord[0] = varray_texcoord2f[0];
1498 dobloomblend = false;
1500 // do both in one pass if possible
1501 if (r_textureunits.integer >= 2 && gl_combine.integer)
1503 dobloomblend = false;
1504 m.texcombinergb[1] = GL_ADD;
1505 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1506 m.pointer_texcoord[1] = varray_texcoord2f[1];
1509 dobloomblend = true;
1512 GL_BlendFunc(GL_ONE, GL_ZERO);
1514 R_Mesh_Draw(0, 4, 2, polygonelements);
1515 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1516 // now blend on the bloom texture if multipass
1519 memset(&m, 0, sizeof(m));
1520 m.pointer_vertex = varray_vertex3f;
1521 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1522 m.pointer_texcoord[0] = varray_texcoord2f[1];
1524 GL_BlendFunc(GL_ONE, GL_ONE);
1526 R_Mesh_Draw(0, 4, 2, polygonelements);
1527 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1532 // apply a color tint to the whole view
1533 memset(&m, 0, sizeof(m));
1534 m.pointer_vertex = varray_vertex3f;
1536 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1537 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1538 R_Mesh_Draw(0, 4, 2, polygonelements);
1542 void R_RenderScene(void);
1544 matrix4x4_t r_waterscrollmatrix;
1551 void R_RenderView(void)
1553 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1554 return; //Host_Error ("R_RenderView: NULL worldmodel");
1556 r_view_width = bound(0, r_refdef.width, vid.width);
1557 r_view_height = bound(0, r_refdef.height, vid.height);
1559 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1560 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1562 r_view_matrix = r_refdef.viewentitymatrix;
1563 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1564 r_rtworld = r_shadow_realtime_world.integer;
1565 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1566 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1567 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1568 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1570 // GL is weird because it's bottom to top, r_view_y is top to bottom
1571 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1572 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1573 GL_ScissorTest(true);
1578 if (r_timereport_active)
1579 R_TimeReport("setup");
1581 qglDepthFunc(GL_LEQUAL);
1582 qglPolygonOffset(0, 0);
1583 qglEnable(GL_POLYGON_OFFSET_FILL);
1587 qglPolygonOffset(0, 0);
1588 qglDisable(GL_POLYGON_OFFSET_FILL);
1591 if (r_timereport_active)
1592 R_TimeReport("blendview");
1594 GL_Scissor(0, 0, vid.width, vid.height);
1595 GL_ScissorTest(false);
1599 void CSQC_R_ClearScreen (void)
1601 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1602 return; //Host_Error ("R_RenderView: NULL worldmodel");
1604 r_view_width = bound(0, r_refdef.width, vid.width);
1605 r_view_height = bound(0, r_refdef.height, vid.height);
1607 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1608 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1610 r_view_matrix = r_refdef.viewentitymatrix;
1611 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1612 r_rtworld = r_shadow_realtime_world.integer;
1613 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1614 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1615 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1616 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1618 // GL is weird because it's bottom to top, r_view_y is top to bottom
1619 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1620 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1621 GL_ScissorTest(true);
1626 if (r_timereport_active)
1627 R_TimeReport("setup");
1631 void CSQC_R_RenderScene (void)
1633 qglDepthFunc(GL_LEQUAL);
1634 qglPolygonOffset(0, 0);
1635 qglEnable(GL_POLYGON_OFFSET_FILL);
1639 qglPolygonOffset(0, 0);
1640 qglDisable(GL_POLYGON_OFFSET_FILL);
1643 if (r_timereport_active)
1644 R_TimeReport("blendview");
1646 GL_Scissor(0, 0, vid.width, vid.height);
1647 GL_ScissorTest(false);
1650 extern void R_DrawLightningBeams (void);
1651 extern void VM_AddPolygonsToMeshQueue (void);
1652 void R_RenderScene(void)
1656 // don't let sound skip if going slow
1657 if (r_refdef.extraupdate)
1662 R_MeshQueue_BeginScene();
1666 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1667 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1669 if (r_rtworldshadows || r_rtdlightshadows)
1670 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1672 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1674 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1676 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);
1680 R_WorldVisibility();
1681 if (r_timereport_active)
1682 R_TimeReport("worldvis");
1685 if (r_timereport_active)
1686 R_TimeReport("markentity");
1688 R_Shadow_UpdateWorldLightSelection();
1690 for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1696 GL_BlendFunc(GL_ONE, GL_ONE);
1697 GL_DepthTest(!r_showdisabledepthtest.integer);
1698 GL_DepthMask(GL_FALSE);
1699 memset(&m, 0, sizeof(m));
1701 //qglEnable(GL_LINE_SMOOTH);
1702 qglEnable(GL_POLYGON_OFFSET_LINE);
1703 qglPolygonOffset(0, r_showtris_polygonoffset.value);
1707 if (cl.csqc_vidvars.drawworld)
1709 // don't let sound skip if going slow
1710 if (r_refdef.extraupdate)
1714 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1715 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1717 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1718 if (r_timereport_active)
1719 R_TimeReport("worldsky");
1722 if (R_DrawBrushModelsSky() && r_timereport_active)
1723 R_TimeReport("bmodelsky");
1726 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1727 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1729 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1730 if (r_timereport_active)
1731 R_TimeReport("world");
1735 // don't let sound skip if going slow
1736 if (r_refdef.extraupdate)
1740 GL_ShowTrisColor(0, 0.015, 0, 1);
1743 if (r_timereport_active)
1744 R_TimeReport("models");
1746 // don't let sound skip if going slow
1747 if (r_refdef.extraupdate)
1751 GL_ShowTrisColor(0, 0, 0.033, 1);
1752 R_ShadowVolumeLighting(false);
1753 if (r_timereport_active)
1754 R_TimeReport("rtlights");
1756 // don't let sound skip if going slow
1757 if (r_refdef.extraupdate)
1761 GL_ShowTrisColor(0.1, 0, 0, 1);
1763 if (cl.csqc_vidvars.drawworld)
1765 R_DrawLightningBeams();
1766 if (r_timereport_active)
1767 R_TimeReport("lightning");
1770 if (r_timereport_active)
1771 R_TimeReport("particles");
1774 if (r_timereport_active)
1775 R_TimeReport("explosions");
1778 R_MeshQueue_RenderTransparent();
1779 if (r_timereport_active)
1780 R_TimeReport("drawtrans");
1782 if (cl.csqc_vidvars.drawworld)
1785 if (r_timereport_active)
1786 R_TimeReport("coronas");
1788 if(cl.csqc_vidvars.drawcrosshair)
1790 R_DrawWorldCrosshair();
1791 if (r_timereport_active)
1792 R_TimeReport("crosshair");
1795 VM_AddPolygonsToMeshQueue();
1797 R_MeshQueue_Render();
1801 //qglDisable(GL_LINE_SMOOTH);
1802 qglDisable(GL_POLYGON_OFFSET_LINE);
1808 R_MeshQueue_EndScene();
1810 // don't let sound skip if going slow
1811 if (r_refdef.extraupdate)
1816 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1819 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1821 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1822 GL_DepthMask(false);
1824 R_Mesh_Matrix(&identitymatrix);
1826 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1827 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1828 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1829 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1830 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1831 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1832 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1833 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1834 R_FillColors(color, 8, cr, cg, cb, ca);
1837 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1839 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
1841 c[0] = c[0] * f1 + fogcolor[0] * f2;
1842 c[1] = c[1] * f1 + fogcolor[1] * f2;
1843 c[2] = c[2] * f1 + fogcolor[2] * f2;
1846 memset(&m, 0, sizeof(m));
1847 m.pointer_vertex = vertex3f;
1848 m.pointer_color = color;
1854 int nomodelelements[24] =
1866 float nomodelvertex3f[6*3] =
1876 float nomodelcolor4f[6*4] =
1878 0.0f, 0.0f, 0.5f, 1.0f,
1879 0.0f, 0.0f, 0.5f, 1.0f,
1880 0.0f, 0.5f, 0.0f, 1.0f,
1881 0.0f, 0.5f, 0.0f, 1.0f,
1882 0.5f, 0.0f, 0.0f, 1.0f,
1883 0.5f, 0.0f, 0.0f, 1.0f
1886 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
1892 R_Mesh_Matrix(&ent->matrix);
1894 memset(&m, 0, sizeof(m));
1895 m.pointer_vertex = nomodelvertex3f;
1897 if (ent->flags & EF_ADDITIVE)
1899 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1900 GL_DepthMask(false);
1902 else if (ent->alpha < 1)
1904 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1905 GL_DepthMask(false);
1909 GL_BlendFunc(GL_ONE, GL_ZERO);
1912 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1915 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1916 m.pointer_color = color4f;
1917 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
1919 for (i = 0, c = color4f;i < 6;i++, c += 4)
1921 c[0] = (c[0] * f1 + fogcolor[0] * f2);
1922 c[1] = (c[1] * f1 + fogcolor[1] * f2);
1923 c[2] = (c[2] * f1 + fogcolor[2] * f2);
1927 else if (ent->alpha != 1)
1929 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1930 m.pointer_color = color4f;
1931 for (i = 0, c = color4f;i < 6;i++, c += 4)
1935 m.pointer_color = nomodelcolor4f;
1937 R_Mesh_Draw(0, 6, 8, nomodelelements);
1940 void R_DrawNoModel(entity_render_t *ent)
1942 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1943 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
1945 // R_DrawNoModelCallback(ent, 0);
1948 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1950 vec3_t right1, right2, diff, normal;
1952 VectorSubtract (org2, org1, normal);
1954 // calculate 'right' vector for start
1955 VectorSubtract (r_vieworigin, org1, diff);
1956 CrossProduct (normal, diff, right1);
1957 VectorNormalize (right1);
1959 // calculate 'right' vector for end
1960 VectorSubtract (r_vieworigin, org2, diff);
1961 CrossProduct (normal, diff, right2);
1962 VectorNormalize (right2);
1964 vert[ 0] = org1[0] + width * right1[0];
1965 vert[ 1] = org1[1] + width * right1[1];
1966 vert[ 2] = org1[2] + width * right1[2];
1967 vert[ 3] = org1[0] - width * right1[0];
1968 vert[ 4] = org1[1] - width * right1[1];
1969 vert[ 5] = org1[2] - width * right1[2];
1970 vert[ 6] = org2[0] - width * right2[0];
1971 vert[ 7] = org2[1] - width * right2[1];
1972 vert[ 8] = org2[2] - width * right2[2];
1973 vert[ 9] = org2[0] + width * right2[0];
1974 vert[10] = org2[1] + width * right2[1];
1975 vert[11] = org2[2] + width * right2[2];
1978 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1980 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)
1982 float fog = 0.0f, ifog;
1986 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
1989 R_Mesh_Matrix(&identitymatrix);
1990 GL_BlendFunc(blendfunc1, blendfunc2);
1991 GL_DepthMask(false);
1992 GL_DepthTest(!depthdisable);
1994 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1995 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1996 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1997 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1998 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1999 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2000 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2001 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2002 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2003 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2004 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2005 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2007 memset(&m, 0, sizeof(m));
2008 m.tex[0] = R_GetTexture(texture);
2009 m.pointer_texcoord[0] = spritetexcoord2f;
2010 m.pointer_vertex = varray_vertex3f;
2012 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2013 R_Mesh_Draw(0, 4, 2, polygonelements);
2015 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2017 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2018 GL_BlendFunc(blendfunc1, GL_ONE);
2019 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2020 R_Mesh_Draw(0, 4, 2, polygonelements);
2024 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2028 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2029 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2031 if (i == mesh->numvertices)
2033 if (mesh->numvertices < mesh->maxvertices)
2035 VectorCopy(v, vertex3f);
2036 mesh->numvertices++;
2038 return mesh->numvertices;
2044 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2048 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2049 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2050 e = mesh->element3i + mesh->numtriangles * 3;
2051 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2053 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2054 if (mesh->numtriangles < mesh->maxtriangles)
2059 mesh->numtriangles++;
2061 element[1] = element[2];
2065 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2067 int planenum, planenum2;
2070 mplane_t *plane, *plane2;
2071 float temppoints[2][256*3];
2072 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2076 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2077 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2079 if (planenum2 == planenum)
2081 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);
2084 if (tempnumpoints < 3)
2086 // generate elements forming a triangle fan for this polygon
2087 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2091 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)
2093 texturelayer_t *layer;
2094 layer = t->currentlayers + t->currentnumlayers++;
2096 layer->depthmask = depthmask;
2097 layer->blendfunc1 = blendfunc1;
2098 layer->blendfunc2 = blendfunc2;
2099 layer->texture = texture;
2100 layer->texmatrix = *matrix;
2101 layer->color[0] = r;
2102 layer->color[1] = g;
2103 layer->color[2] = b;
2104 layer->color[3] = a;
2107 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2109 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2110 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2113 texture_t *texture = t;
2114 model_t *model = ent->model;
2115 int s = ent->skinnum;
2116 if ((unsigned int)s >= (unsigned int)model->numskins)
2118 if (model->skinscenes)
2120 if (model->skinscenes[s].framecount > 1)
2121 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2123 s = model->skinscenes[s].firstframe;
2126 t = t + s * model->num_surfaces;
2128 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];
2129 texture->currentframe = t;
2132 t->currentmaterialflags = t->basematerialflags;
2133 t->currentalpha = ent->alpha;
2134 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2135 t->currentalpha *= r_wateralpha.value;
2136 if (!(ent->flags & RENDER_LIGHT))
2137 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2138 if (ent->effects & EF_ADDITIVE)
2139 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2140 else if (t->currentalpha < 1)
2141 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2142 if (ent->effects & EF_NODEPTHTEST)
2143 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2144 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2145 t->currenttexmatrix = r_waterscrollmatrix;
2147 t->currenttexmatrix = identitymatrix;
2148 t->currentnumlayers = 0;
2149 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2151 if (gl_lightmaps.integer)
2152 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2153 else if (t->currentmaterialflags & MATERIALFLAG_SKY)
2155 // transparent sky would be ridiculous
2156 if (!(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2157 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_SKY, r_texture_white, &identitymatrix, fogcolor[0], fogcolor[1], fogcolor[2], 1);
2161 int blendfunc1, blendfunc2, depthmask;
2162 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2164 blendfunc1 = GL_SRC_ALPHA;
2165 blendfunc2 = GL_ONE;
2168 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2170 blendfunc1 = GL_SRC_ALPHA;
2171 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2176 blendfunc1 = GL_ONE;
2177 blendfunc2 = GL_ZERO;
2180 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2182 rtexture_t *currentbasetexture;
2184 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2185 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2186 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2187 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2189 // fullbright is not affected by r_lightmapintensity
2190 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2191 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2192 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);
2193 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2194 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);
2200 // q3bsp has no lightmap updates, so the lightstylevalue that
2201 // would normally be baked into the lightmaptexture must be
2202 // applied to the color
2203 if (ent->model->type == mod_brushq3)
2204 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2205 colorscale *= r_lightmapintensity;
2206 if (r_textureunits.integer >= 2 && gl_combine.integer)
2207 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);
2208 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2209 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);
2211 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);
2212 if (r_ambient.value >= (1.0f/64.0f))
2213 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);
2214 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2216 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);
2217 if (r_ambient.value >= (1.0f/64.0f))
2218 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);
2220 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2222 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);
2223 if (r_ambient.value >= (1.0f/64.0f))
2224 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);
2227 if (t->skin.glow != NULL)
2228 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2229 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2231 // if this is opaque use alpha blend which will darken the earlier
2234 // if this is an alpha blended material, all the earlier passes
2235 // were darkened by fog already, so we only need to add the fog
2236 // color ontop through the fog mask texture
2238 // if this is an additive blended material, all the earlier passes
2239 // were darkened by fog already, and we should not add fog color
2240 // (because the background was not darkened, there is no fog color
2241 // that was lost behind it).
2242 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);
2249 void R_UpdateAllTextureInfo(entity_render_t *ent)
2253 for (i = 0;i < ent->model->num_textures;i++)
2254 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2257 float *rsurface_vertex3f;
2258 float *rsurface_svector3f;
2259 float *rsurface_tvector3f;
2260 float *rsurface_normal3f;
2261 float *rsurface_lightmapcolor4f;
2263 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
2265 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
2267 rsurface_vertex3f = varray_vertex3f;
2268 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
2269 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2271 rsurface_svector3f = varray_svector3f;
2272 rsurface_tvector3f = varray_tvector3f;
2273 rsurface_normal3f = varray_normal3f;
2274 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);
2278 rsurface_svector3f = NULL;
2279 rsurface_tvector3f = NULL;
2280 if (generatenormals)
2282 rsurface_normal3f = varray_normal3f;
2283 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);
2286 rsurface_normal3f = NULL;
2291 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
2292 rsurface_svector3f = surface->groupmesh->data_svector3f;
2293 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
2294 rsurface_normal3f = surface->groupmesh->data_normal3f;
2296 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2299 float center[3], forward[3], right[3], up[3], v[4][3];
2300 matrix4x4_t matrix1, imatrix1;
2301 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
2302 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
2303 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
2304 // a single autosprite surface can contain multiple sprites...
2305 for (j = 0;j < surface->num_vertices - 3;j += 4)
2307 VectorClear(center);
2308 for (i = 0;i < 4;i++)
2309 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2310 VectorScale(center, 0.25f, center);
2311 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2312 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);
2313 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2314 for (i = 0;i < 4;i++)
2315 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2316 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2318 forward[0] = modelorg[0] - center[0];
2319 forward[1] = modelorg[1] - center[1];
2321 VectorNormalize(forward);
2322 right[0] = forward[1];
2323 right[1] = -forward[0];
2325 VectorSet(up, 0, 0, 1);
2327 for (i = 0;i < 4;i++)
2328 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
2330 rsurface_vertex3f = varray_vertex3f;
2331 rsurface_svector3f = varray_svector3f;
2332 rsurface_tvector3f = varray_tvector3f;
2333 rsurface_normal3f = varray_normal3f;
2334 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);
2336 R_Mesh_VertexPointer(rsurface_vertex3f);
2339 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)
2344 RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode == 2, false);
2348 vec4_t ambientcolor4f;
2349 vec3_t diffusecolor;
2350 vec3_t diffusenormal;
2351 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
2353 rsurface_lightmapcolor4f = varray_color4f;
2354 R_LightModel_CalcVertexColors(ambientcolor4f, diffusecolor, diffusenormal, surface->groupmesh->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, rsurface_lightmapcolor4f + 4 * surface->num_firstvertex);
2363 r = ambientcolor4f[0];
2364 g = ambientcolor4f[1];
2365 b = ambientcolor4f[2];
2366 a = ambientcolor4f[3];
2367 rsurface_lightmapcolor4f = NULL;
2370 else if (lightmode >= 1)
2372 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2374 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2376 if (surface->lightmapinfo->samples)
2378 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
2379 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2380 VectorScale(lm, scale, c);
2381 if (surface->lightmapinfo->styles[1] != 255)
2383 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2385 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2386 VectorMA(c, scale, lm, c);
2387 if (surface->lightmapinfo->styles[2] != 255)
2390 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2391 VectorMA(c, scale, lm, c);
2392 if (surface->lightmapinfo->styles[3] != 255)
2395 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2396 VectorMA(c, scale, lm, c);
2404 rsurface_lightmapcolor4f = varray_color4f;
2407 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
2410 rsurface_lightmapcolor4f = NULL;
2413 if (rsurface_lightmapcolor4f)
2415 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)
2417 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2426 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)
2428 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2435 rsurface_lightmapcolor4f = varray_color4f;
2437 if (applycolor && rsurface_lightmapcolor4f)
2439 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)
2446 rsurface_lightmapcolor4f = varray_color4f;
2448 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2449 GL_Color(r, g, b, a);
2450 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2451 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2452 GL_LockArrays(0, 0);
2455 static void RSurf_Draw(const msurface_t *surface)
2457 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2458 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2459 GL_LockArrays(0, 0);
2462 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2464 int texturesurfaceindex;
2466 const msurface_t *surface;
2467 qboolean applycolor;
2470 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2472 renderstats.entities_surfaces += texturenumsurfaces;
2473 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2474 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2475 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2476 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2477 qglDisable(GL_CULL_FACE);
2478 if (texture->currentnumlayers)
2481 texturelayer_t *layer;
2482 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2485 int layertexrgbscale;
2486 GL_DepthMask(layer->depthmask);
2487 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2488 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2490 layertexrgbscale = 4;
2491 VectorScale(layer->color, 0.25f, layercolor);
2493 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2495 layertexrgbscale = 2;
2496 VectorScale(layer->color, 0.5f, layercolor);
2500 layertexrgbscale = 1;
2501 VectorScale(layer->color, 1.0f, layercolor);
2503 layercolor[3] = layer->color[3];
2504 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2505 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2506 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2507 switch (layer->type)
2509 case TEXTURELAYERTYPE_SKY:
2512 skyrendernow = false;
2513 if (skyrendermasked)
2516 // restore entity matrix and GL_Color
2517 R_Mesh_Matrix(&ent->matrix);
2518 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2521 // LordHavoc: HalfLife maps have freaky skypolys...
2522 //if (!ent->model->brush.ishlbsp)
2524 if (skyrendermasked)
2526 // depth-only (masking)
2527 GL_ColorMask(0,0,0,0);
2528 // just to make sure that braindead drivers don't draw anything
2529 // despite that colormask...
2530 GL_BlendFunc(GL_ZERO, GL_ONE);
2535 GL_BlendFunc(GL_ONE, GL_ZERO);
2537 memset(&m, 0, sizeof(m));
2539 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2541 surface = texturesurfacelist[texturesurfaceindex];
2542 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2543 RSurf_Draw(surface);
2545 if (skyrendermasked)
2546 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2549 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2550 memset(&m, 0, sizeof(m));
2551 m.tex[1] = R_GetTexture(layer->texture);
2552 m.texmatrix[1] = layer->texmatrix;
2553 m.texrgbscale[1] = layertexrgbscale;
2554 m.pointer_color = varray_color4f;
2558 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2560 surface = texturesurfacelist[texturesurfaceindex];
2561 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2562 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2563 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2564 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2569 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2571 surface = texturesurfacelist[texturesurfaceindex];
2572 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2573 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2574 if (surface->lightmaptexture)
2576 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2577 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2581 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2582 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2587 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2588 memset(&m, 0, sizeof(m));
2589 m.tex[0] = R_GetTexture(layer->texture);
2590 m.texmatrix[0] = layer->texmatrix;
2591 m.pointer_color = varray_color4f;
2592 m.texrgbscale[0] = layertexrgbscale;
2596 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2598 surface = texturesurfacelist[texturesurfaceindex];
2599 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2600 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2601 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2606 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2608 surface = texturesurfacelist[texturesurfaceindex];
2609 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2610 if (surface->lightmaptexture)
2612 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2613 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
2617 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2618 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2622 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2623 memset(&m, 0, sizeof(m));
2624 m.tex[0] = R_GetTexture(layer->texture);
2625 m.texmatrix[0] = layer->texmatrix;
2626 m.pointer_color = varray_color4f;
2627 m.texrgbscale[0] = layertexrgbscale;
2629 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2631 surface = texturesurfacelist[texturesurfaceindex];
2632 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2633 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2636 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2637 memset(&m, 0, sizeof(m));
2638 m.tex[0] = R_GetTexture(layer->texture);
2639 m.texmatrix[0] = layer->texmatrix;
2640 m.texrgbscale[0] = layertexrgbscale;
2641 m.pointer_color = varray_color4f;
2645 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2647 surface = texturesurfacelist[texturesurfaceindex];
2648 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2649 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2654 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2656 surface = texturesurfacelist[texturesurfaceindex];
2657 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2658 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2662 case TEXTURELAYERTYPE_TEXTURE:
2663 memset(&m, 0, sizeof(m));
2664 m.tex[0] = R_GetTexture(layer->texture);
2665 m.texmatrix[0] = layer->texmatrix;
2666 m.pointer_color = varray_color4f;
2667 m.texrgbscale[0] = layertexrgbscale;
2669 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2671 surface = texturesurfacelist[texturesurfaceindex];
2672 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2673 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2676 case TEXTURELAYERTYPE_FOG:
2677 memset(&m, 0, sizeof(m));
2680 m.tex[0] = R_GetTexture(layer->texture);
2681 m.texmatrix[0] = layer->texmatrix;
2684 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2688 surface = texturesurfacelist[texturesurfaceindex];
2689 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2691 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2692 R_Mesh_ColorPointer(varray_color4f);
2693 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)
2695 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2696 c[0] = layercolor[0];
2697 c[1] = layercolor[1];
2698 c[2] = layercolor[2];
2699 c[3] = f * layercolor[3];
2701 RSurf_Draw(surface);
2705 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2707 // if trying to do overbright on first pass of an opaque surface
2708 // when combine is not supported, brighten as a post process
2709 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
2712 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2713 GL_Color(1, 1, 1, 1);
2714 memset(&m, 0, sizeof(m));
2716 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2718 surface = texturesurfacelist[texturesurfaceindex];
2719 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2720 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
2721 RSurf_Draw(surface);
2725 if (r_shownormals.integer && !r_showtrispass)
2729 GL_DepthTest(!r_showdisabledepthtest.integer);
2730 GL_DepthMask(texture->currentlayers->depthmask);
2731 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
2732 memset(&m, 0, sizeof(m));
2734 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2736 surface = texturesurfacelist[texturesurfaceindex];
2737 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2738 GL_Color(1, 0, 0, 1);
2740 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2742 VectorCopy(rsurface_vertex3f + k * 3, v);
2743 qglVertex3f(v[0], v[1], v[2]);
2744 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
2745 qglVertex3f(v[0], v[1], v[2]);
2747 GL_Color(0, 0, 1, 1);
2748 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2750 VectorCopy(rsurface_vertex3f + k * 3, v);
2751 qglVertex3f(v[0], v[1], v[2]);
2752 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
2753 qglVertex3f(v[0], v[1], v[2]);
2755 GL_Color(0, 1, 0, 1);
2756 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
2758 VectorCopy(rsurface_vertex3f + k * 3, v);
2759 qglVertex3f(v[0], v[1], v[2]);
2760 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
2761 qglVertex3f(v[0], v[1], v[2]);
2767 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2768 qglEnable(GL_CULL_FACE);
2771 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2773 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
2777 texture = surface->texture;
2778 if (texture->basematerialflags & MATERIALFLAG_SKY)
2779 return; // transparent sky is too difficult
2780 R_UpdateTextureInfo(ent, texture);
2782 R_Mesh_Matrix(&ent->matrix);
2783 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2784 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2787 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2789 int texturesurfaceindex;
2790 const msurface_t *surface;
2791 vec3_t tempcenter, center;
2792 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2794 // drawing sky transparently would be too difficult
2795 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2797 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2799 surface = texturesurfacelist[texturesurfaceindex];
2800 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2801 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2802 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2803 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2804 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
2809 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2812 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2813 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2815 int i, j, f, flagsmask;
2816 int counttriangles = 0;
2817 msurface_t *surface, **surfacechain;
2818 texture_t *t, *texture;
2819 model_t *model = ent->model;
2821 const int maxsurfacelist = 1024;
2822 int numsurfacelist = 0;
2823 const msurface_t *surfacelist[1024];
2826 R_Mesh_Matrix(&ent->matrix);
2827 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2829 // update light styles
2830 if (!skysurfaces && model->brushq1.light_styleupdatechains)
2832 for (i = 0;i < model->brushq1.light_styles;i++)
2834 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
2836 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
2837 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2838 for (;(surface = *surfacechain);surfacechain++)
2839 surface->cached_dlight = true;
2844 R_UpdateAllTextureInfo(ent);
2845 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2850 if (ent == r_refdef.worldentity)
2852 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2854 if (!r_worldsurfacevisible[j])
2856 if (t != surface->texture)
2860 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2863 t = surface->texture;
2864 texture = t->currentframe;
2865 f = texture->currentmaterialflags & flagsmask;
2867 if (f && surface->num_triangles)
2869 // if lightmap parameters changed, rebuild lightmap texture
2870 if (surface->cached_dlight)
2871 R_BuildLightMap(ent, surface);
2872 // add face to draw list
2873 surfacelist[numsurfacelist++] = surface;
2874 counttriangles += surface->num_triangles;
2875 if (numsurfacelist >= maxsurfacelist)
2877 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2885 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2887 if (t != surface->texture)
2891 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2894 t = surface->texture;
2895 texture = t->currentframe;
2896 f = texture->currentmaterialflags & flagsmask;
2898 if (f && surface->num_triangles)
2900 // if lightmap parameters changed, rebuild lightmap texture
2901 if (surface->cached_dlight)
2902 R_BuildLightMap(ent, surface);
2903 // add face to draw list
2904 surfacelist[numsurfacelist++] = surface;
2905 counttriangles += surface->num_triangles;
2906 if (numsurfacelist >= maxsurfacelist)
2908 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2915 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2916 if (!r_showtrispass)
2917 renderstats.entities_triangles += counttriangles;