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"
431 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
432 "varying vec2 TexCoordLightmap;\n"
435 "#ifdef MODE_LIGHTSOURCE\n"
436 "varying myhvec3 CubeVector;\n"
439 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
440 "varying vec3 LightVector;\n"
443 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
444 "varying vec3 EyeVector;\n"
450 "// vertex shader specific:\n"
451 "#ifdef VERTEX_SHADER\n"
453 "#ifdef MODE_LIGHTSOURCE\n"
454 "uniform vec3 LightPosition;\n"
457 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
458 "uniform vec3 EyePosition;\n"
461 "#ifdef MODE_LIGHTDIRECTION\n"
462 "uniform myhvec3 LightDir;\n"
465 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
469 " // copy the surface texcoord\n"
470 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
471 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
472 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
474 " gl_FrontColor = gl_Color;\n"
476 "#ifdef MODE_LIGHTSOURCE\n"
477 " // transform vertex position into light attenuation/cubemap space\n"
478 " // (-1 to +1 across the light box)\n"
479 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
481 " // transform unnormalized light direction into tangent space\n"
482 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
483 " // normalize it per pixel)\n"
484 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
485 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
486 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
487 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
490 "#ifdef MODE_LIGHTDIRECTION\n"
491 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
492 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
493 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
496 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
497 " // transform unnormalized eye direction into tangent space\n"
498 " vec3 eyeminusvertex = EyePosition - gl_Vertex.xyz;\n"
499 " EyeVector.x = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);\n"
500 " EyeVector.y = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);\n"
501 " EyeVector.z = dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n"
504 " // transform vertex to camera space, using ftransform to match non-VS\n"
506 " gl_Position = ftransform();\n"
514 "// fragment shader specific:\n"
515 "#ifdef FRAGMENT_SHADER\n"
517 "uniform myhvec3 LightColor;\n"
518 "#ifdef USEOFFSETMAPPING\n"
519 "uniform myhalf OffsetMapping_Scale;\n"
520 "uniform myhalf OffsetMapping_Bias;\n"
523 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTIONMAP) || defined(MODE_LIGHTDIRECTION) || defined(USEOFFSETMAPPING)\n"
524 "uniform sampler2D Texture_Normal;\n"
527 "#ifdef MODE_LIGHTDIRECTION\n"
528 "uniform myhvec3 AmbientColor;\n"
529 "uniform myhvec3 DiffuseColor;\n"
530 "uniform myhvec3 SpecularColor;\n"
533 "uniform sampler2D Texture_Color;\n"
535 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
536 "uniform sampler2D Texture_Lightmap;\n"
538 "#ifdef MODE_LIGHTDIRECTIONMAP\n"
539 "uniform sampler2D Texture_Deluxemap;\n"
543 "uniform sampler2D Texture_Glow;\n"
546 "#ifdef USECOLORMAPPING\n"
547 "uniform sampler2D Texture_Pants;\n"
548 "uniform sampler2D Texture_Shirt;\n"
549 "uniform myhvec3 Color_Pants;\n"
550 "uniform myhvec3 Color_Shirt;\n"
553 "uniform myhalf AmbientScale;\n"
554 "uniform myhalf DiffuseScale;\n"
555 "#ifdef USESPECULAR\n"
556 "uniform myhalf SpecularScale;\n"
557 "uniform myhalf SpecularPower;\n"
558 "uniform sampler2D Texture_Gloss;\n"
561 "#ifdef USECUBEFILTER\n"
562 "uniform samplerCube Texture_Cube;\n"
566 "uniform myhvec3 FogColor;\n"
567 "uniform myhalf FogRangeRecip;\n"
568 "uniform sampler2D Texture_FogMask;\n"
571 "#ifdef USEEASTEREGG\n"
574 " gl_FragColor = myhvec4(0, 0, 0, 1);;\n"
577 " vec2 p = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
578 " vec2 c = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
579 " for (i = 0;i < 1000 && dot(p,p) < 4.0;i = i + 1)\n"
581 " o = p.x * p.x - p.y * p.y;\n"
582 " p.y = 2.0 * p.x * p.y;\n"
586 " o = float(i) * 0.314;\n"
588 " gl_FragColor = vec4(cos(o), sin(o), sin(o * 0.2), 1);\n"
590 "#else // USEEASTEREGG\n"
596 " // apply offsetmapping\n"
597 "#ifdef USEOFFSETMAPPING\n"
598 " // this is 3 sample because of ATI Radeon 9500-9800/X300 limits\n"
599 " myhvec2 OffsetVector = normalize(EyeVector).xy * vec2(-0.333, 0.333);\n"
600 " myhvec2 TexCoordOffset = TexCoord + OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).w);\n"
601 " TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoordOffset).w);\n"
602 " TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoordOffset).w);\n"
603 "#define TexCoord TexCoordOffset\n"
606 " // combine the diffuse textures (base, pants, shirt)\n"
607 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
608 "#ifdef USECOLORMAPPING\n"
609 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
615 "#ifdef MODE_LIGHTSOURCE\n"
618 " // get the surface normal and light normal\n"
619 "#ifdef SURFACENORMALIZE\n"
620 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
622 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
624 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
626 " // calculate directional shading\n"
627 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
628 "#ifdef USESPECULAR\n"
629 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
630 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
633 "#ifdef USECUBEFILTER\n"
634 " // apply light cubemap filter\n"
635 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
638 " // apply light color\n"
639 " color.rgb = color.rgb * LightColor;\n"
641 " // apply attenuation\n"
643 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
644 " // center and sharp falloff at the edge, this is about the most efficient\n"
645 " // we can get away with as far as providing illumination.\n"
647 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
648 " // provide significant illumination, large = slow = pain.\n"
649 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
654 "#elif defined(MODE_LIGHTDIRECTION)\n"
655 " // directional model lighting\n"
657 " // get the surface normal and light normal\n"
658 "#ifdef SURFACENORMALIZE\n"
659 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
661 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
663 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
666 " // calculate directional shading\n"
667 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
668 "#ifdef USESPECULAR\n"
669 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
670 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
676 "#elif defined(MODE_LIGHTDIRECTIONMAP)\n"
677 " // deluxemap lightmapping\n"
679 " // get the surface normal and light normal\n"
680 "#ifdef SURFACENORMALIZE\n"
681 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
682 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
684 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
685 " myhvec3 diffusenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap));\n"
688 " // calculate directional shading\n"
689 " myhvec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
690 "#ifdef USESPECULAR\n"
691 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
692 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
695 " // apply lightmap color\n"
696 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * myhvec3(AmbientScale);\n"
701 "#else // MODE none (lightmap)\n"
702 " // apply lightmap color\n"
703 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
707 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord));\n"
712 " myhalf fog = texture2D(Texture_FogMask, myhvec2(length(EyeVector)*FogRangeRecip, 0.0)).x;\n"
713 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
716 " gl_FragColor = color * gl_Color;\n"
718 "#endif // !USEEASTEREGG\n"
723 void R_GLSL_CompilePermutation(int permutation)
725 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
726 int vertstrings_count;
727 int fragstrings_count;
729 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
730 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
731 char permutationname[256];
735 vertstrings_list[0] = "#define VERTEX_SHADER\n";
736 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
737 vertstrings_count = 1;
738 fragstrings_count = 1;
739 permutationname[0] = 0;
740 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
742 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
743 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
744 strlcat(permutationname, " lightsource", sizeof(permutationname));
746 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP)
748 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP\n";
749 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP\n";
750 strlcat(permutationname, " lightdirectionmap", sizeof(permutationname));
752 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
754 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
755 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
756 strlcat(permutationname, " lightdirection", sizeof(permutationname));
758 if (permutation & SHADERPERMUTATION_GLOW)
760 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
761 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
762 strlcat(permutationname, " glow", sizeof(permutationname));
764 if (permutation & SHADERPERMUTATION_COLORMAPPING)
766 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
767 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
768 strlcat(permutationname, " colormapping", sizeof(permutationname));
770 if (permutation & SHADERPERMUTATION_SPECULAR)
772 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
773 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
774 strlcat(permutationname, " specular", sizeof(permutationname));
776 if (permutation & SHADERPERMUTATION_FOG)
778 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
779 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
780 strlcat(permutationname, " fog", sizeof(permutationname));
782 if (permutation & SHADERPERMUTATION_CUBEFILTER)
784 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
785 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
786 strlcat(permutationname, " cubefilter", sizeof(permutationname));
788 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
790 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
791 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
792 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
794 if (permutation & SHADERPERMUTATION_SURFACENORMALIZE)
796 vertstrings_list[vertstrings_count++] = "#define SURFACENORMALIZE\n";
797 fragstrings_list[fragstrings_count++] = "#define SURFACENORMALIZE\n";
798 strlcat(permutationname, " surfacenormalize", sizeof(permutationname));
800 if (permutation & SHADERPERMUTATION_GEFORCEFX)
802 vertstrings_list[vertstrings_count++] = "#define GEFORCEFX\n";
803 fragstrings_list[fragstrings_count++] = "#define GEFORCEFX\n";
804 strlcat(permutationname, " halffloat", sizeof(permutationname));
806 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
809 Con_DPrintf("GLSL shader text loaded from disk\n");
810 vertstrings_list[vertstrings_count++] = shaderstring;
811 fragstrings_list[fragstrings_count++] = shaderstring;
815 vertstrings_list[vertstrings_count++] = builtinshaderstring;
816 fragstrings_list[fragstrings_count++] = builtinshaderstring;
818 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
822 qglUseProgramObjectARB(p->program);
823 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
824 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
825 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
826 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
827 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
828 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
829 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
830 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
831 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
832 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
833 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
834 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
835 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
836 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
837 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
838 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
839 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
840 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
841 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
842 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
843 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
844 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
845 p->loc_OffsetMapping_Bias = qglGetUniformLocationARB(p->program, "OffsetMapping_Bias");
846 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
847 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
848 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
849 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
850 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
851 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
852 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
853 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
854 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
855 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
856 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
857 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
858 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
859 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
860 qglUseProgramObjectARB(0);
864 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
866 Mem_Free(shaderstring);
869 void R_GLSL_Restart_f(void)
872 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
873 if (r_glsl_permutations[i].program)
874 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
875 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
878 void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting)
880 // select a permutation of the lighting shader appropriate to this
881 // combination of texture, entity, light source, and fogging, only use the
882 // minimum features necessary to avoid wasting rendering time in the
883 // fragment shader on features that are not being used
885 float specularscale = texture->specularscale;
886 r_glsl_permutation = NULL;
887 if (r_shadow_rtlight)
889 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
890 specularscale *= r_shadow_rtlight->specularscale;
891 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
892 permutation |= SHADERPERMUTATION_CUBEFILTER;
894 else if (modellighting)
896 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
897 if (texture->skin.glow)
898 permutation |= SHADERPERMUTATION_GLOW;
900 else if (r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
902 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP;
903 if (texture->skin.glow)
904 permutation |= SHADERPERMUTATION_GLOW;
908 if (texture->skin.glow)
909 permutation |= SHADERPERMUTATION_GLOW;
911 if (specularscale > 0)
912 permutation |= SHADERPERMUTATION_SPECULAR;
914 permutation |= SHADERPERMUTATION_FOG;
915 if (texture->colormapping)
916 permutation |= SHADERPERMUTATION_COLORMAPPING;
917 if (r_glsl_offsetmapping.integer)
918 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
919 if (r_glsl_surfacenormalize.integer)
920 permutation |= SHADERPERMUTATION_SURFACENORMALIZE;
921 if (r_glsl_usehalffloat.integer)
922 permutation |= SHADERPERMUTATION_GEFORCEFX;
923 if (!r_glsl_permutations[permutation].program)
925 if (!r_glsl_permutations[permutation].compiled)
926 R_GLSL_CompilePermutation(permutation);
927 if (!r_glsl_permutations[permutation].program)
929 // remove features until we find a valid permutation
931 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
933 // reduce i more quickly whenever it would not remove any bits
937 if (!r_glsl_permutations[permutation].compiled)
938 R_GLSL_CompilePermutation(permutation);
939 if (r_glsl_permutations[permutation].program)
942 return; // utterly failed
946 r_glsl_permutation = r_glsl_permutations + permutation;
948 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
949 R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
950 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
952 R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
953 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
954 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, r_shadow_entitylightorigin[0], r_shadow_entitylightorigin[1], r_shadow_entitylightorigin[2]);
955 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
956 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
957 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
958 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
960 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
962 if (texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
964 if (r_glsl_permutation->loc_AmbientColor >= 0)
965 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, 1, 1, 1);
966 if (r_glsl_permutation->loc_DiffuseColor >= 0)
967 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, 0, 0, 0);
968 if (r_glsl_permutation->loc_SpecularColor >= 0)
969 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, 0, 0, 0);
970 if (r_glsl_permutation->loc_LightDir >= 0)
971 qglUniform3fARB(r_glsl_permutation->loc_LightDir, 0, 0, -1);
975 if (r_glsl_permutation->loc_AmbientColor >= 0)
976 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
977 if (r_glsl_permutation->loc_DiffuseColor >= 0)
978 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
979 if (r_glsl_permutation->loc_SpecularColor >= 0)
980 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
981 if (r_glsl_permutation->loc_LightDir >= 0)
982 qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->modellight_lightdir[2]);
987 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
988 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
989 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale * 2.0f);
991 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(texture->skin.nmap));
992 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
993 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
994 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
995 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
996 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
997 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
998 if (r_glsl_permutation->loc_FogColor >= 0)
1000 // additive passes are only darkened by fog, not tinted
1001 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
1002 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1004 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
1006 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
1007 if (r_glsl_permutation->loc_Color_Pants >= 0)
1009 if (texture->skin.pants)
1010 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
1012 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1014 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1016 if (texture->skin.shirt)
1017 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
1019 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1021 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
1022 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
1023 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1024 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Bias, r_glsl_offsetmapping_bias.value);
1028 void gl_main_start(void)
1030 // use half float math where available (speed gain on NVIDIA GFFX and GF6)
1031 if (gl_support_half_float)
1032 Cvar_SetValue("r_glsl_usehalffloat", 1);
1033 r_main_texturepool = R_AllocTexturePool();
1034 r_bloom_texture_screen = NULL;
1035 r_bloom_texture_bloom = NULL;
1036 R_BuildBlankTextures();
1038 if (gl_texturecubemap)
1041 R_BuildNormalizationCube();
1043 R_BuildFogTexture();
1044 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1047 void gl_main_shutdown(void)
1049 R_FreeTexturePool(&r_main_texturepool);
1050 r_bloom_texture_screen = NULL;
1051 r_bloom_texture_bloom = NULL;
1052 r_texture_blanknormalmap = NULL;
1053 r_texture_white = NULL;
1054 r_texture_black = NULL;
1055 r_texture_whitecube = NULL;
1056 r_texture_normalizationcube = NULL;
1060 extern void CL_ParseEntityLump(char *entitystring);
1061 void gl_main_newmap(void)
1063 // FIXME: move this code to client
1065 char *entities, entname[MAX_QPATH];
1069 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1070 l = (int)strlen(entname) - 4;
1071 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1073 strcpy(entname + l, ".ent");
1074 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1076 CL_ParseEntityLump(entities);
1081 if (cl.worldmodel->brush.entities)
1082 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1086 void GL_Main_Init(void)
1088 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1090 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1091 FOG_registercvars(); // FIXME: move this fog stuff to client?
1092 Cvar_RegisterVariable(&r_nearclip);
1093 Cvar_RegisterVariable(&r_showtris);
1094 Cvar_RegisterVariable(&r_showtris_polygonoffset);
1095 Cvar_RegisterVariable(&r_shownormals);
1096 Cvar_RegisterVariable(&r_showlighting);
1097 Cvar_RegisterVariable(&r_showshadowvolumes);
1098 Cvar_RegisterVariable(&r_showcollisionbrushes);
1099 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1100 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1101 Cvar_RegisterVariable(&r_showdisabledepthtest);
1102 Cvar_RegisterVariable(&r_drawentities);
1103 Cvar_RegisterVariable(&r_drawviewmodel);
1104 Cvar_RegisterVariable(&r_speeds);
1105 Cvar_RegisterVariable(&r_fullbrights);
1106 Cvar_RegisterVariable(&r_wateralpha);
1107 Cvar_RegisterVariable(&r_dynamic);
1108 Cvar_RegisterVariable(&r_fullbright);
1109 Cvar_RegisterVariable(&r_textureunits);
1110 Cvar_RegisterVariable(&r_glsl);
1111 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1112 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1113 Cvar_RegisterVariable(&r_glsl_offsetmapping_bias);
1114 Cvar_RegisterVariable(&r_glsl_usehalffloat);
1115 Cvar_RegisterVariable(&r_glsl_surfacenormalize);
1116 Cvar_RegisterVariable(&r_lerpsprites);
1117 Cvar_RegisterVariable(&r_lerpmodels);
1118 Cvar_RegisterVariable(&r_waterscroll);
1119 Cvar_RegisterVariable(&r_bloom);
1120 Cvar_RegisterVariable(&r_bloom_intensity);
1121 Cvar_RegisterVariable(&r_bloom_blur);
1122 Cvar_RegisterVariable(&r_bloom_resolution);
1123 Cvar_RegisterVariable(&r_bloom_power);
1124 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1125 Cvar_RegisterVariable(&developer_texturelogging);
1126 Cvar_RegisterVariable(&gl_lightmaps);
1127 Cvar_RegisterVariable(&r_test);
1128 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1129 Cvar_SetValue("r_fullbrights", 0);
1130 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1133 static vec3_t r_farclip_origin;
1134 static vec3_t r_farclip_direction;
1135 static vec_t r_farclip_directiondist;
1136 static vec_t r_farclip_meshfarclip;
1137 static int r_farclip_directionbit0;
1138 static int r_farclip_directionbit1;
1139 static int r_farclip_directionbit2;
1141 // enlarge farclip to accomodate box
1142 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1145 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1146 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1147 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1148 if (r_farclip_meshfarclip < d)
1149 r_farclip_meshfarclip = d;
1152 // return farclip value
1153 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1157 VectorCopy(origin, r_farclip_origin);
1158 VectorCopy(direction, r_farclip_direction);
1159 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1160 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1161 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1162 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1163 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1165 if (r_refdef.worldmodel)
1166 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1167 for (i = 0;i < r_refdef.numentities;i++)
1168 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1170 return r_farclip_meshfarclip - r_farclip_directiondist;
1173 extern void R_Textures_Init(void);
1174 extern void GL_Draw_Init(void);
1175 extern void GL_Main_Init(void);
1176 extern void R_Shadow_Init(void);
1177 extern void R_Sky_Init(void);
1178 extern void GL_Surf_Init(void);
1179 extern void R_Crosshairs_Init(void);
1180 extern void R_Light_Init(void);
1181 extern void R_Particles_Init(void);
1182 extern void R_Explosion_Init(void);
1183 extern void gl_backend_init(void);
1184 extern void Sbar_Init(void);
1185 extern void R_LightningBeams_Init(void);
1186 extern void Mod_RenderInit(void);
1188 void Render_Init(void)
1198 R_Crosshairs_Init();
1203 R_LightningBeams_Init();
1212 extern char *ENGINE_EXTENSIONS;
1215 VID_CheckExtensions();
1217 // LordHavoc: report supported extensions
1218 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1220 // clear to black (loading plaque will be seen over this)
1221 qglClearColor(0,0,0,1);
1222 qglClear(GL_COLOR_BUFFER_BIT);
1225 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1229 for (i = 0;i < 4;i++)
1236 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1240 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1244 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1248 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1252 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1256 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1260 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1264 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1272 //==================================================================================
1274 static void R_UpdateEntityLighting(entity_render_t *ent)
1276 vec3_t tempdiffusenormal;
1277 VectorSet(ent->modellight_ambient, r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f));
1278 VectorClear(ent->modellight_diffuse);
1279 VectorClear(ent->modellight_lightdir);
1280 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1281 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1283 VectorSet(ent->modellight_ambient, 1, 1, 1);
1284 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1285 VectorNormalize(ent->modellight_lightdir);
1286 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1287 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1288 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1289 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1290 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1291 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1294 static void R_MarkEntities (void)
1297 entity_render_t *ent;
1299 if (!r_drawentities.integer)
1302 r_refdef.worldentity->visframe = r_framecount;
1303 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1304 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1306 // worldmodel can check visibility
1307 for (i = 0;i < r_refdef.numentities;i++)
1309 ent = r_refdef.entities[i];
1310 // some of the renderer still relies on origin...
1311 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1312 // some of the renderer still relies on scale...
1313 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1314 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)))
1316 ent->visframe = r_framecount;
1317 R_UpdateEntityLighting(ent);
1323 // no worldmodel or it can't check visibility
1324 for (i = 0;i < r_refdef.numentities;i++)
1326 ent = r_refdef.entities[i];
1327 // some of the renderer still relies on origin...
1328 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1329 // some of the renderer still relies on scale...
1330 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1331 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1333 ent->visframe = r_framecount;
1334 R_UpdateEntityLighting(ent);
1340 // only used if skyrendermasked, and normally returns false
1341 int R_DrawBrushModelsSky (void)
1344 entity_render_t *ent;
1346 if (!r_drawentities.integer)
1350 for (i = 0;i < r_refdef.numentities;i++)
1352 ent = r_refdef.entities[i];
1353 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1355 ent->model->DrawSky(ent);
1362 void R_DrawNoModel(entity_render_t *ent);
1363 void R_DrawModels(void)
1366 entity_render_t *ent;
1368 if (!r_drawentities.integer)
1371 for (i = 0;i < r_refdef.numentities;i++)
1373 ent = r_refdef.entities[i];
1374 if (ent->visframe == r_framecount)
1376 renderstats.entities++;
1377 if (ent->model && ent->model->Draw != NULL)
1378 ent->model->Draw(ent);
1385 static void R_SetFrustum(void)
1387 // break apart the view matrix into vectors for various purposes
1388 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1389 VectorNegate(r_viewleft, r_viewright);
1392 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1393 frustum[0].normal[1] = 0 - 0;
1394 frustum[0].normal[2] = -1 - 0;
1395 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1396 frustum[1].normal[1] = 0 + 0;
1397 frustum[1].normal[2] = -1 + 0;
1398 frustum[2].normal[0] = 0 - 0;
1399 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1400 frustum[2].normal[2] = -1 - 0;
1401 frustum[3].normal[0] = 0 + 0;
1402 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1403 frustum[3].normal[2] = -1 + 0;
1407 zNear = r_nearclip.value;
1408 nudge = 1.0 - 1.0 / (1<<23);
1409 frustum[4].normal[0] = 0 - 0;
1410 frustum[4].normal[1] = 0 - 0;
1411 frustum[4].normal[2] = -1 - -nudge;
1412 frustum[4].dist = 0 - -2 * zNear * nudge;
1413 frustum[5].normal[0] = 0 + 0;
1414 frustum[5].normal[1] = 0 + 0;
1415 frustum[5].normal[2] = -1 + -nudge;
1416 frustum[5].dist = 0 + -2 * zNear * nudge;
1422 frustum[0].normal[0] = m[3] - m[0];
1423 frustum[0].normal[1] = m[7] - m[4];
1424 frustum[0].normal[2] = m[11] - m[8];
1425 frustum[0].dist = m[15] - m[12];
1427 frustum[1].normal[0] = m[3] + m[0];
1428 frustum[1].normal[1] = m[7] + m[4];
1429 frustum[1].normal[2] = m[11] + m[8];
1430 frustum[1].dist = m[15] + m[12];
1432 frustum[2].normal[0] = m[3] - m[1];
1433 frustum[2].normal[1] = m[7] - m[5];
1434 frustum[2].normal[2] = m[11] - m[9];
1435 frustum[2].dist = m[15] - m[13];
1437 frustum[3].normal[0] = m[3] + m[1];
1438 frustum[3].normal[1] = m[7] + m[5];
1439 frustum[3].normal[2] = m[11] + m[9];
1440 frustum[3].dist = m[15] + m[13];
1442 frustum[4].normal[0] = m[3] - m[2];
1443 frustum[4].normal[1] = m[7] - m[6];
1444 frustum[4].normal[2] = m[11] - m[10];
1445 frustum[4].dist = m[15] - m[14];
1447 frustum[5].normal[0] = m[3] + m[2];
1448 frustum[5].normal[1] = m[7] + m[6];
1449 frustum[5].normal[2] = m[11] + m[10];
1450 frustum[5].dist = m[15] + m[14];
1455 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1456 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1457 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1458 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1459 VectorCopy(r_viewforward, frustum[4].normal);
1460 VectorNormalize(frustum[0].normal);
1461 VectorNormalize(frustum[1].normal);
1462 VectorNormalize(frustum[2].normal);
1463 VectorNormalize(frustum[3].normal);
1464 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1465 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1466 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1467 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1468 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1469 PlaneClassify(&frustum[0]);
1470 PlaneClassify(&frustum[1]);
1471 PlaneClassify(&frustum[2]);
1472 PlaneClassify(&frustum[3]);
1473 PlaneClassify(&frustum[4]);
1475 // LordHavoc: note to all quake engine coders, Quake had a special case
1476 // for 90 degrees which assumed a square view (wrong), so I removed it,
1477 // Quake2 has it disabled as well.
1479 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1480 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1481 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1482 //PlaneClassify(&frustum[0]);
1484 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1485 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1486 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1487 //PlaneClassify(&frustum[1]);
1489 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1490 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1491 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1492 //PlaneClassify(&frustum[2]);
1494 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1495 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1496 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1497 //PlaneClassify(&frustum[3]);
1500 //VectorCopy(r_viewforward, frustum[4].normal);
1501 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1502 //PlaneClassify(&frustum[4]);
1505 static void R_BlendView(void)
1507 int screenwidth, screenheight;
1512 // set the (poorly named) screenwidth and screenheight variables to
1513 // a power of 2 at least as large as the screen, these will define the
1514 // size of the texture to allocate
1515 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1516 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1518 doblend = r_refdef.viewblend[3] >= 0.01f;
1519 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;
1521 if (!dobloom && !doblend)
1524 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1526 GL_DepthTest(false);
1527 R_Mesh_Matrix(&identitymatrix);
1528 // vertex coordinates for a quad that covers the screen exactly
1529 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
1530 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
1531 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
1532 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
1535 int bloomwidth, bloomheight, x, dobloomblend, range;
1536 float xoffset, yoffset, r;
1537 renderstats.bloom++;
1538 // allocate textures as needed
1539 if (!r_bloom_texture_screen)
1540 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1541 if (!r_bloom_texture_bloom)
1542 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1543 // set bloomwidth and bloomheight to the bloom resolution that will be
1544 // used (often less than the screen resolution for faster rendering)
1545 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1546 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1547 // set up a texcoord array for the full resolution screen image
1548 // (we have to keep this around to copy back during final render)
1549 varray_texcoord2f[0][0] = 0;
1550 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1551 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1552 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1553 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1554 varray_texcoord2f[0][5] = 0;
1555 varray_texcoord2f[0][6] = 0;
1556 varray_texcoord2f[0][7] = 0;
1557 // set up a texcoord array for the reduced resolution bloom image
1558 // (which will be additive blended over the screen image)
1559 varray_texcoord2f[1][0] = 0;
1560 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1561 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1562 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1563 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1564 varray_texcoord2f[1][5] = 0;
1565 varray_texcoord2f[1][6] = 0;
1566 varray_texcoord2f[1][7] = 0;
1567 memset(&m, 0, sizeof(m));
1568 m.pointer_vertex = varray_vertex3f;
1569 m.pointer_texcoord[0] = varray_texcoord2f[0];
1570 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1572 // copy view into the full resolution screen image texture
1573 GL_ActiveTexture(0);
1574 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1575 renderstats.bloom_copypixels += r_view_width * r_view_height;
1576 // now scale it down to the bloom size and raise to a power of itself
1577 // to darken it (this leaves the really bright stuff bright, and
1578 // everything else becomes very dark)
1579 // TODO: optimize with multitexture or GLSL
1580 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1581 GL_BlendFunc(GL_ONE, GL_ZERO);
1582 GL_Color(1, 1, 1, 1);
1583 R_Mesh_Draw(0, 4, 2, polygonelements);
1584 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1585 // render multiple times with a multiply blendfunc to raise to a power
1586 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1587 for (x = 1;x < r_bloom_power.integer;x++)
1589 R_Mesh_Draw(0, 4, 2, polygonelements);
1590 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1592 // we now have a darkened bloom image in the framebuffer, copy it into
1593 // the bloom image texture for more processing
1594 memset(&m, 0, sizeof(m));
1595 m.pointer_vertex = varray_vertex3f;
1596 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1597 m.pointer_texcoord[0] = varray_texcoord2f[2];
1599 GL_ActiveTexture(0);
1600 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1601 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1602 // blend on at multiple vertical offsets to achieve a vertical blur
1603 // TODO: do offset blends using GLSL
1604 range = r_bloom_blur.integer * bloomwidth / 320;
1605 GL_BlendFunc(GL_ONE, GL_ZERO);
1606 for (x = -range;x <= range;x++)
1608 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1609 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1610 // compute a texcoord array with the specified x and y offset
1611 varray_texcoord2f[2][0] = xoffset+0;
1612 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1613 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1614 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1615 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1616 varray_texcoord2f[2][5] = yoffset+0;
1617 varray_texcoord2f[2][6] = xoffset+0;
1618 varray_texcoord2f[2][7] = yoffset+0;
1619 // this r value looks like a 'dot' particle, fading sharply to
1620 // black at the edges
1621 // (probably not realistic but looks good enough)
1622 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1625 GL_Color(r, r, r, 1);
1626 R_Mesh_Draw(0, 4, 2, polygonelements);
1627 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1628 GL_BlendFunc(GL_ONE, GL_ONE);
1630 // copy the vertically blurred bloom view to a texture
1631 GL_ActiveTexture(0);
1632 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1633 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1634 // blend the vertically blurred image at multiple offsets horizontally
1635 // to finish the blur effect
1636 // TODO: do offset blends using GLSL
1637 range = r_bloom_blur.integer * bloomwidth / 320;
1638 GL_BlendFunc(GL_ONE, GL_ZERO);
1639 for (x = -range;x <= range;x++)
1641 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1642 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1643 // compute a texcoord array with the specified x and y offset
1644 varray_texcoord2f[2][0] = xoffset+0;
1645 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1646 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1647 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1648 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1649 varray_texcoord2f[2][5] = yoffset+0;
1650 varray_texcoord2f[2][6] = xoffset+0;
1651 varray_texcoord2f[2][7] = yoffset+0;
1652 // this r value looks like a 'dot' particle, fading sharply to
1653 // black at the edges
1654 // (probably not realistic but looks good enough)
1655 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1658 GL_Color(r, r, r, 1);
1659 R_Mesh_Draw(0, 4, 2, polygonelements);
1660 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1661 GL_BlendFunc(GL_ONE, GL_ONE);
1663 // copy the blurred bloom view to a texture
1664 GL_ActiveTexture(0);
1665 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1666 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1667 // go back to full view area
1668 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1669 // put the original screen image back in place and blend the bloom
1671 memset(&m, 0, sizeof(m));
1672 m.pointer_vertex = varray_vertex3f;
1673 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1674 m.pointer_texcoord[0] = varray_texcoord2f[0];
1676 dobloomblend = false;
1678 // do both in one pass if possible
1679 if (r_textureunits.integer >= 2 && gl_combine.integer)
1681 dobloomblend = false;
1682 m.texcombinergb[1] = GL_ADD;
1683 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1684 m.pointer_texcoord[1] = varray_texcoord2f[1];
1687 dobloomblend = true;
1690 GL_BlendFunc(GL_ONE, GL_ZERO);
1692 R_Mesh_Draw(0, 4, 2, polygonelements);
1693 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1694 // now blend on the bloom texture if multipass
1697 memset(&m, 0, sizeof(m));
1698 m.pointer_vertex = varray_vertex3f;
1699 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1700 m.pointer_texcoord[0] = varray_texcoord2f[1];
1702 GL_BlendFunc(GL_ONE, GL_ONE);
1704 R_Mesh_Draw(0, 4, 2, polygonelements);
1705 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1710 // apply a color tint to the whole view
1711 memset(&m, 0, sizeof(m));
1712 m.pointer_vertex = varray_vertex3f;
1714 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1715 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1716 R_Mesh_Draw(0, 4, 2, polygonelements);
1720 void R_RenderScene(void);
1722 matrix4x4_t r_waterscrollmatrix;
1729 void R_RenderView(void)
1731 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1732 return; //Host_Error ("R_RenderView: NULL worldmodel");
1734 r_view_width = bound(0, r_refdef.width, vid.width);
1735 r_view_height = bound(0, r_refdef.height, vid.height);
1737 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1738 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1740 r_view_matrix = r_refdef.viewentitymatrix;
1741 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1742 r_rtworld = r_shadow_realtime_world.integer;
1743 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1744 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1745 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1746 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1748 // GL is weird because it's bottom to top, r_view_y is top to bottom
1749 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1750 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1751 GL_ScissorTest(true);
1756 if (r_timereport_active)
1757 R_TimeReport("setup");
1759 qglDepthFunc(GL_LEQUAL);
1760 qglPolygonOffset(0, 0);
1761 qglEnable(GL_POLYGON_OFFSET_FILL);
1765 qglPolygonOffset(0, 0);
1766 qglDisable(GL_POLYGON_OFFSET_FILL);
1769 if (r_timereport_active)
1770 R_TimeReport("blendview");
1772 GL_Scissor(0, 0, vid.width, vid.height);
1773 GL_ScissorTest(false);
1777 void CSQC_R_ClearScreen (void)
1779 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1780 return; //Host_Error ("R_RenderView: NULL worldmodel");
1782 r_view_width = bound(0, r_refdef.width, vid.width);
1783 r_view_height = bound(0, r_refdef.height, vid.height);
1785 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1786 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1788 r_view_matrix = r_refdef.viewentitymatrix;
1789 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1790 r_rtworld = r_shadow_realtime_world.integer;
1791 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1792 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1793 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1794 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1796 // GL is weird because it's bottom to top, r_view_y is top to bottom
1797 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1798 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1799 GL_ScissorTest(true);
1804 if (r_timereport_active)
1805 R_TimeReport("setup");
1809 void CSQC_R_RenderScene (void)
1811 qglDepthFunc(GL_LEQUAL);
1812 qglPolygonOffset(0, 0);
1813 qglEnable(GL_POLYGON_OFFSET_FILL);
1817 qglPolygonOffset(0, 0);
1818 qglDisable(GL_POLYGON_OFFSET_FILL);
1821 if (r_timereport_active)
1822 R_TimeReport("blendview");
1824 GL_Scissor(0, 0, vid.width, vid.height);
1825 GL_ScissorTest(false);
1828 extern void R_DrawLightningBeams (void);
1829 extern void VM_AddPolygonsToMeshQueue (void);
1830 void R_RenderScene(void)
1834 // don't let sound skip if going slow
1835 if (r_refdef.extraupdate)
1840 if (gl_support_fragment_shader)
1841 qglUseProgramObjectARB(0);
1843 R_MeshQueue_BeginScene();
1847 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1848 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1850 if (r_rtworldshadows || r_rtdlightshadows)
1851 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1853 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1855 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1857 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);
1861 R_WorldVisibility();
1862 if (r_timereport_active)
1863 R_TimeReport("worldvis");
1866 if (r_timereport_active)
1867 R_TimeReport("markentity");
1869 R_Shadow_UpdateWorldLightSelection();
1871 for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1877 GL_BlendFunc(GL_ONE, GL_ONE);
1878 GL_DepthTest(!r_showdisabledepthtest.integer);
1879 GL_DepthMask(GL_FALSE);
1880 memset(&m, 0, sizeof(m));
1882 //qglEnable(GL_LINE_SMOOTH);
1883 qglEnable(GL_POLYGON_OFFSET_LINE);
1884 qglPolygonOffset(0, r_showtris_polygonoffset.value);
1888 if (cl.csqc_vidvars.drawworld)
1890 // don't let sound skip if going slow
1891 if (r_refdef.extraupdate)
1895 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1896 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1898 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1899 if (r_timereport_active)
1900 R_TimeReport("worldsky");
1903 if (R_DrawBrushModelsSky() && r_timereport_active)
1904 R_TimeReport("bmodelsky");
1907 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1908 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1910 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1911 if (r_timereport_active)
1912 R_TimeReport("world");
1916 // don't let sound skip if going slow
1917 if (r_refdef.extraupdate)
1921 GL_ShowTrisColor(0, 0.015, 0, 1);
1924 if (r_timereport_active)
1925 R_TimeReport("models");
1927 // don't let sound skip if going slow
1928 if (r_refdef.extraupdate)
1932 GL_ShowTrisColor(0, 0, 0.033, 1);
1933 R_ShadowVolumeLighting(false);
1934 if (r_timereport_active)
1935 R_TimeReport("rtlights");
1937 // don't let sound skip if going slow
1938 if (r_refdef.extraupdate)
1942 GL_ShowTrisColor(0.1, 0, 0, 1);
1944 if (cl.csqc_vidvars.drawworld)
1946 R_DrawLightningBeams();
1947 if (r_timereport_active)
1948 R_TimeReport("lightning");
1951 if (r_timereport_active)
1952 R_TimeReport("particles");
1955 if (r_timereport_active)
1956 R_TimeReport("explosions");
1959 R_MeshQueue_RenderTransparent();
1960 if (r_timereport_active)
1961 R_TimeReport("drawtrans");
1963 if (cl.csqc_vidvars.drawworld)
1966 if (r_timereport_active)
1967 R_TimeReport("coronas");
1969 if(cl.csqc_vidvars.drawcrosshair)
1971 R_DrawWorldCrosshair();
1972 if (r_timereport_active)
1973 R_TimeReport("crosshair");
1976 VM_AddPolygonsToMeshQueue();
1978 R_MeshQueue_Render();
1982 //qglDisable(GL_LINE_SMOOTH);
1983 qglDisable(GL_POLYGON_OFFSET_LINE);
1989 R_MeshQueue_EndScene();
1991 // don't let sound skip if going slow
1992 if (r_refdef.extraupdate)
1995 if (gl_support_fragment_shader)
1996 qglUseProgramObjectARB(0);
2000 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2003 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2005 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2006 GL_DepthMask(false);
2008 R_Mesh_Matrix(&identitymatrix);
2010 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2011 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2012 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2013 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2014 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2015 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2016 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2017 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2018 R_FillColors(color, 8, cr, cg, cb, ca);
2021 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2023 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
2025 c[0] = c[0] * f1 + fogcolor[0] * f2;
2026 c[1] = c[1] * f1 + fogcolor[1] * f2;
2027 c[2] = c[2] * f1 + fogcolor[2] * f2;
2030 memset(&m, 0, sizeof(m));
2031 m.pointer_vertex = vertex3f;
2032 m.pointer_color = color;
2038 int nomodelelements[24] =
2050 float nomodelvertex3f[6*3] =
2060 float nomodelcolor4f[6*4] =
2062 0.0f, 0.0f, 0.5f, 1.0f,
2063 0.0f, 0.0f, 0.5f, 1.0f,
2064 0.0f, 0.5f, 0.0f, 1.0f,
2065 0.0f, 0.5f, 0.0f, 1.0f,
2066 0.5f, 0.0f, 0.0f, 1.0f,
2067 0.5f, 0.0f, 0.0f, 1.0f
2070 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2076 R_Mesh_Matrix(&ent->matrix);
2078 memset(&m, 0, sizeof(m));
2079 m.pointer_vertex = nomodelvertex3f;
2081 if (ent->flags & EF_ADDITIVE)
2083 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2084 GL_DepthMask(false);
2086 else if (ent->alpha < 1)
2088 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2089 GL_DepthMask(false);
2093 GL_BlendFunc(GL_ONE, GL_ZERO);
2096 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2099 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2100 m.pointer_color = color4f;
2101 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2103 for (i = 0, c = color4f;i < 6;i++, c += 4)
2105 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2106 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2107 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2111 else if (ent->alpha != 1)
2113 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2114 m.pointer_color = color4f;
2115 for (i = 0, c = color4f;i < 6;i++, c += 4)
2119 m.pointer_color = nomodelcolor4f;
2121 R_Mesh_Draw(0, 6, 8, nomodelelements);
2124 void R_DrawNoModel(entity_render_t *ent)
2126 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2127 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2129 // R_DrawNoModelCallback(ent, 0);
2132 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2134 vec3_t right1, right2, diff, normal;
2136 VectorSubtract (org2, org1, normal);
2138 // calculate 'right' vector for start
2139 VectorSubtract (r_vieworigin, org1, diff);
2140 CrossProduct (normal, diff, right1);
2141 VectorNormalize (right1);
2143 // calculate 'right' vector for end
2144 VectorSubtract (r_vieworigin, org2, diff);
2145 CrossProduct (normal, diff, right2);
2146 VectorNormalize (right2);
2148 vert[ 0] = org1[0] + width * right1[0];
2149 vert[ 1] = org1[1] + width * right1[1];
2150 vert[ 2] = org1[2] + width * right1[2];
2151 vert[ 3] = org1[0] - width * right1[0];
2152 vert[ 4] = org1[1] - width * right1[1];
2153 vert[ 5] = org1[2] - width * right1[2];
2154 vert[ 6] = org2[0] - width * right2[0];
2155 vert[ 7] = org2[1] - width * right2[1];
2156 vert[ 8] = org2[2] - width * right2[2];
2157 vert[ 9] = org2[0] + width * right2[0];
2158 vert[10] = org2[1] + width * right2[1];
2159 vert[11] = org2[2] + width * right2[2];
2162 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2164 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)
2166 float fog = 0.0f, ifog;
2170 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2173 R_Mesh_Matrix(&identitymatrix);
2174 GL_BlendFunc(blendfunc1, blendfunc2);
2175 GL_DepthMask(false);
2176 GL_DepthTest(!depthdisable);
2178 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2179 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2180 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2181 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2182 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2183 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2184 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2185 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2186 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2187 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2188 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2189 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2191 memset(&m, 0, sizeof(m));
2192 m.tex[0] = R_GetTexture(texture);
2193 m.pointer_texcoord[0] = spritetexcoord2f;
2194 m.pointer_vertex = varray_vertex3f;
2196 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2197 R_Mesh_Draw(0, 4, 2, polygonelements);
2199 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2201 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2202 GL_BlendFunc(blendfunc1, GL_ONE);
2203 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2204 R_Mesh_Draw(0, 4, 2, polygonelements);
2208 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2212 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2213 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2215 if (i == mesh->numvertices)
2217 if (mesh->numvertices < mesh->maxvertices)
2219 VectorCopy(v, vertex3f);
2220 mesh->numvertices++;
2222 return mesh->numvertices;
2228 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2232 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2233 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2234 e = mesh->element3i + mesh->numtriangles * 3;
2235 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2237 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2238 if (mesh->numtriangles < mesh->maxtriangles)
2243 mesh->numtriangles++;
2245 element[1] = element[2];
2249 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2251 int planenum, planenum2;
2254 mplane_t *plane, *plane2;
2255 float temppoints[2][256*3];
2256 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2260 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2261 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2263 if (planenum2 == planenum)
2265 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);
2268 if (tempnumpoints < 3)
2270 // generate elements forming a triangle fan for this polygon
2271 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2275 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)
2277 texturelayer_t *layer;
2278 layer = t->currentlayers + t->currentnumlayers++;
2280 layer->depthmask = depthmask;
2281 layer->blendfunc1 = blendfunc1;
2282 layer->blendfunc2 = blendfunc2;
2283 layer->texture = texture;
2284 layer->texmatrix = *matrix;
2285 layer->color[0] = r;
2286 layer->color[1] = g;
2287 layer->color[2] = b;
2288 layer->color[3] = a;
2291 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2293 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2294 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2297 texture_t *texture = t;
2298 model_t *model = ent->model;
2299 int s = ent->skinnum;
2300 if ((unsigned int)s >= (unsigned int)model->numskins)
2302 if (model->skinscenes)
2304 if (model->skinscenes[s].framecount > 1)
2305 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2307 s = model->skinscenes[s].firstframe;
2310 t = t + s * model->num_surfaces;
2312 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];
2313 texture->currentframe = t;
2316 t->currentmaterialflags = t->basematerialflags;
2317 t->currentalpha = ent->alpha;
2318 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2319 t->currentalpha *= r_wateralpha.value;
2320 if (!(ent->flags & RENDER_LIGHT))
2321 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2322 if (ent->effects & EF_ADDITIVE)
2323 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2324 else if (t->currentalpha < 1)
2325 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2326 if (ent->effects & EF_NODEPTHTEST)
2327 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2328 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2329 t->currenttexmatrix = r_waterscrollmatrix;
2331 t->currenttexmatrix = identitymatrix;
2333 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2334 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2335 t->glosstexture = r_texture_white;
2336 t->specularpower = 8;
2337 t->specularscale = 0;
2338 if (r_shadow_gloss.integer > 0)
2342 if (r_shadow_glossintensity.value > 0)
2344 t->glosstexture = t->skin.gloss;
2345 t->specularscale = r_shadow_glossintensity.value;
2348 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2349 t->specularscale = r_shadow_gloss2intensity.value;
2352 t->currentnumlayers = 0;
2353 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2355 if (gl_lightmaps.integer)
2356 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2357 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2359 int blendfunc1, blendfunc2, depthmask;
2360 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2362 blendfunc1 = GL_SRC_ALPHA;
2363 blendfunc2 = GL_ONE;
2366 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2368 blendfunc1 = GL_SRC_ALPHA;
2369 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2374 blendfunc1 = GL_ONE;
2375 blendfunc2 = GL_ZERO;
2378 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2380 rtexture_t *currentbasetexture;
2382 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2383 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2384 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2385 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2387 // fullbright is not affected by r_lightmapintensity
2388 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2389 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2390 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);
2391 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2392 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);
2398 // q3bsp has no lightmap updates, so the lightstylevalue that
2399 // would normally be baked into the lightmaptexture must be
2400 // applied to the color
2401 if (ent->model->type == mod_brushq3)
2402 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2403 colorscale *= r_lightmapintensity;
2404 if (r_textureunits.integer >= 2 && gl_combine.integer)
2405 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);
2406 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2407 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);
2409 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);
2410 if (r_ambient.value >= (1.0f/64.0f))
2411 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);
2412 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2414 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);
2415 if (r_ambient.value >= (1.0f/64.0f))
2416 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);
2418 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2420 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);
2421 if (r_ambient.value >= (1.0f/64.0f))
2422 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);
2425 if (t->skin.glow != NULL)
2426 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2427 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2429 // if this is opaque use alpha blend which will darken the earlier
2432 // if this is an alpha blended material, all the earlier passes
2433 // were darkened by fog already, so we only need to add the fog
2434 // color ontop through the fog mask texture
2436 // if this is an additive blended material, all the earlier passes
2437 // were darkened by fog already, and we should not add fog color
2438 // (because the background was not darkened, there is no fog color
2439 // that was lost behind it).
2440 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);
2447 void R_UpdateAllTextureInfo(entity_render_t *ent)
2451 for (i = 0;i < ent->model->num_textures;i++)
2452 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2455 float *rsurface_vertex3f;
2456 float *rsurface_svector3f;
2457 float *rsurface_tvector3f;
2458 float *rsurface_normal3f;
2459 float *rsurface_lightmapcolor4f;
2461 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
2463 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
2465 rsurface_vertex3f = varray_vertex3f;
2466 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
2467 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2469 rsurface_svector3f = varray_svector3f;
2470 rsurface_tvector3f = varray_tvector3f;
2471 rsurface_normal3f = varray_normal3f;
2472 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);
2476 rsurface_svector3f = NULL;
2477 rsurface_tvector3f = NULL;
2478 if (generatenormals)
2480 rsurface_normal3f = varray_normal3f;
2481 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);
2484 rsurface_normal3f = NULL;
2489 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
2490 rsurface_svector3f = surface->groupmesh->data_svector3f;
2491 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
2492 rsurface_normal3f = surface->groupmesh->data_normal3f;
2494 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2497 float center[3], forward[3], right[3], up[3], v[4][3];
2498 matrix4x4_t matrix1, imatrix1;
2499 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
2500 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
2501 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
2502 // a single autosprite surface can contain multiple sprites...
2503 for (j = 0;j < surface->num_vertices - 3;j += 4)
2505 VectorClear(center);
2506 for (i = 0;i < 4;i++)
2507 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2508 VectorScale(center, 0.25f, center);
2509 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2510 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);
2511 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2512 for (i = 0;i < 4;i++)
2513 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2514 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2516 forward[0] = modelorg[0] - center[0];
2517 forward[1] = modelorg[1] - center[1];
2519 VectorNormalize(forward);
2520 right[0] = forward[1];
2521 right[1] = -forward[0];
2523 VectorSet(up, 0, 0, 1);
2525 for (i = 0;i < 4;i++)
2526 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
2528 rsurface_vertex3f = varray_vertex3f;
2529 rsurface_svector3f = varray_svector3f;
2530 rsurface_tvector3f = varray_tvector3f;
2531 rsurface_normal3f = varray_normal3f;
2532 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);
2534 R_Mesh_VertexPointer(rsurface_vertex3f);
2537 static void RSurf_Draw(const msurface_t *surface)
2539 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2540 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2541 GL_LockArrays(0, 0);
2544 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)
2549 RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode >= 2, false);
2553 vec3_t ambientcolor;
2554 vec3_t diffusecolor;
2556 VectorCopy(ent->modellight_lightdir, lightdir);
2557 ambientcolor[0] = ent->modellight_ambient[0] * r * 0.5f;
2558 ambientcolor[1] = ent->modellight_ambient[1] * g * 0.5f;
2559 ambientcolor[2] = ent->modellight_ambient[2] * b * 0.5f;
2560 diffusecolor[0] = ent->modellight_diffuse[0] * r * 0.5f;
2561 diffusecolor[1] = ent->modellight_diffuse[1] * g * 0.5f;
2562 diffusecolor[2] = ent->modellight_diffuse[2] * b * 0.5f;
2563 if (VectorLength2(diffusecolor) > 0)
2565 int numverts = surface->num_vertices;
2566 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2567 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2568 c = varray_color4f + 4 * surface->num_firstvertex;
2569 // q3-style directional shading
2570 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2572 if ((f = DotProduct(c2, lightdir)) > 0)
2573 VectorMA(ambientcolor, f, diffusecolor, c);
2575 VectorCopy(ambientcolor, c);
2583 rsurface_lightmapcolor4f = varray_color4f;
2587 r = ambientcolor[0];
2588 g = ambientcolor[1];
2589 b = ambientcolor[2];
2590 rsurface_lightmapcolor4f = NULL;
2593 else if (lightmode >= 1)
2595 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2597 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2599 if (surface->lightmapinfo->samples)
2601 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
2602 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2603 VectorScale(lm, scale, c);
2604 if (surface->lightmapinfo->styles[1] != 255)
2606 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2608 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2609 VectorMA(c, scale, lm, c);
2610 if (surface->lightmapinfo->styles[2] != 255)
2613 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2614 VectorMA(c, scale, lm, c);
2615 if (surface->lightmapinfo->styles[3] != 255)
2618 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2619 VectorMA(c, scale, lm, c);
2627 rsurface_lightmapcolor4f = varray_color4f;
2630 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
2633 rsurface_lightmapcolor4f = NULL;
2636 if (rsurface_lightmapcolor4f)
2638 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)
2640 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2649 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)
2651 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2658 rsurface_lightmapcolor4f = varray_color4f;
2660 if (applycolor && rsurface_lightmapcolor4f)
2662 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)
2669 rsurface_lightmapcolor4f = varray_color4f;
2671 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2672 GL_Color(r, g, b, a);
2673 RSurf_Draw(surface);
2676 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2678 int texturesurfaceindex;
2680 const msurface_t *surface;
2681 qboolean applycolor;
2684 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2686 r_shadow_rtlight = NULL;
2687 renderstats.entities_surfaces += texturenumsurfaces;
2688 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2689 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2690 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2691 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2692 qglDisable(GL_CULL_FACE);
2693 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2695 // transparent sky would be ridiculous
2696 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2701 skyrendernow = false;
2702 if (skyrendermasked)
2705 // restore entity matrix and GL_Color
2706 R_Mesh_Matrix(&ent->matrix);
2710 // LordHavoc: HalfLife maps have freaky skypolys...
2711 //if (!ent->model->brush.ishlbsp)
2713 if (skyrendermasked)
2715 // depth-only (masking)
2716 GL_ColorMask(0,0,0,0);
2717 // just to make sure that braindead drivers don't draw anything
2718 // despite that colormask...
2719 GL_BlendFunc(GL_ZERO, GL_ONE);
2724 GL_BlendFunc(GL_ONE, GL_ZERO);
2726 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2727 memset(&m, 0, sizeof(m));
2729 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2731 surface = texturesurfacelist[texturesurfaceindex];
2732 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2733 RSurf_Draw(surface);
2735 if (skyrendermasked)
2736 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2740 else if (r_glsl.integer && gl_support_fragment_shader)
2742 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2744 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2745 GL_DepthMask(false);
2747 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2749 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2750 GL_DepthMask(false);
2754 GL_BlendFunc(GL_ONE, GL_ZERO);
2758 memset(&m, 0, sizeof(m));
2760 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2761 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2762 if (!r_glsl_permutation)
2766 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2768 surface = texturesurfacelist[texturesurfaceindex];
2769 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2770 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2771 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2772 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2773 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2774 RSurf_Draw(surface);
2779 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2781 surface = texturesurfacelist[texturesurfaceindex];
2782 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2783 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2784 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2785 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2786 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2787 R_Mesh_TexCoordPointer(4, 2, surface->groupmesh->data_texcoordlightmap2f);
2788 if (surface->lightmaptexture)
2790 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2791 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2792 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2793 //R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2794 R_Mesh_ColorPointer(NULL);
2798 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2799 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2800 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2801 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2803 RSurf_Draw(surface);
2806 qglUseProgramObjectARB(0);
2808 else if (texture->currentnumlayers)
2811 texturelayer_t *layer;
2812 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2815 int layertexrgbscale;
2816 GL_DepthMask(layer->depthmask);
2817 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2818 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2820 layertexrgbscale = 4;
2821 VectorScale(layer->color, 0.25f, layercolor);
2823 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2825 layertexrgbscale = 2;
2826 VectorScale(layer->color, 0.5f, layercolor);
2830 layertexrgbscale = 1;
2831 VectorScale(layer->color, 1.0f, layercolor);
2833 layercolor[3] = layer->color[3];
2834 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2835 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2836 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2837 switch (layer->type)
2839 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2840 memset(&m, 0, sizeof(m));
2841 m.tex[1] = R_GetTexture(layer->texture);
2842 m.texmatrix[1] = layer->texmatrix;
2843 m.texrgbscale[1] = layertexrgbscale;
2844 m.pointer_color = varray_color4f;
2848 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2850 surface = texturesurfacelist[texturesurfaceindex];
2851 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2852 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2853 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2854 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2859 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2861 surface = texturesurfacelist[texturesurfaceindex];
2862 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2863 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2864 if (surface->lightmaptexture)
2866 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2867 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2871 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2872 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2877 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2878 memset(&m, 0, sizeof(m));
2879 m.tex[0] = R_GetTexture(layer->texture);
2880 m.texmatrix[0] = layer->texmatrix;
2881 m.pointer_color = varray_color4f;
2882 m.texrgbscale[0] = layertexrgbscale;
2886 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2888 surface = texturesurfacelist[texturesurfaceindex];
2889 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2890 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2891 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2896 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2898 surface = texturesurfacelist[texturesurfaceindex];
2899 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2900 if (surface->lightmaptexture)
2902 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2903 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
2907 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2908 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2912 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2913 memset(&m, 0, sizeof(m));
2914 m.tex[0] = R_GetTexture(layer->texture);
2915 m.texmatrix[0] = layer->texmatrix;
2916 m.pointer_color = varray_color4f;
2917 m.texrgbscale[0] = layertexrgbscale;
2919 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2921 surface = texturesurfacelist[texturesurfaceindex];
2922 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2923 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2926 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2927 memset(&m, 0, sizeof(m));
2928 m.tex[0] = R_GetTexture(layer->texture);
2929 m.texmatrix[0] = layer->texmatrix;
2930 m.texrgbscale[0] = layertexrgbscale;
2931 m.pointer_color = varray_color4f;
2935 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2937 surface = texturesurfacelist[texturesurfaceindex];
2938 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2939 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2944 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2946 surface = texturesurfacelist[texturesurfaceindex];
2947 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2948 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2952 case TEXTURELAYERTYPE_TEXTURE:
2953 memset(&m, 0, sizeof(m));
2954 m.tex[0] = R_GetTexture(layer->texture);
2955 m.texmatrix[0] = layer->texmatrix;
2956 m.pointer_color = varray_color4f;
2957 m.texrgbscale[0] = layertexrgbscale;
2959 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2961 surface = texturesurfacelist[texturesurfaceindex];
2962 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2963 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2966 case TEXTURELAYERTYPE_FOG:
2967 memset(&m, 0, sizeof(m));
2970 m.tex[0] = R_GetTexture(layer->texture);
2971 m.texmatrix[0] = layer->texmatrix;
2974 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2978 surface = texturesurfacelist[texturesurfaceindex];
2979 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2981 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2982 R_Mesh_ColorPointer(varray_color4f);
2983 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)
2985 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
2986 c[0] = layercolor[0];
2987 c[1] = layercolor[1];
2988 c[2] = layercolor[2];
2989 c[3] = f * layercolor[3];
2991 RSurf_Draw(surface);
2995 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
2997 // if trying to do overbright on first pass of an opaque surface
2998 // when combine is not supported, brighten as a post process
2999 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3002 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3003 GL_Color(1, 1, 1, 1);
3004 memset(&m, 0, sizeof(m));
3006 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3008 surface = texturesurfacelist[texturesurfaceindex];
3009 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
3010 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3011 RSurf_Draw(surface);
3015 if (r_shownormals.integer && !r_showtrispass)
3019 GL_DepthTest(!r_showdisabledepthtest.integer);
3020 GL_DepthMask(texture->currentlayers->depthmask);
3021 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
3022 memset(&m, 0, sizeof(m));
3024 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3026 surface = texturesurfacelist[texturesurfaceindex];
3027 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
3028 GL_Color(1, 0, 0, 1);
3030 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3032 VectorCopy(rsurface_vertex3f + k * 3, v);
3033 qglVertex3f(v[0], v[1], v[2]);
3034 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
3035 qglVertex3f(v[0], v[1], v[2]);
3037 GL_Color(0, 0, 1, 1);
3038 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3040 VectorCopy(rsurface_vertex3f + k * 3, v);
3041 qglVertex3f(v[0], v[1], v[2]);
3042 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
3043 qglVertex3f(v[0], v[1], v[2]);
3045 GL_Color(0, 1, 0, 1);
3046 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3048 VectorCopy(rsurface_vertex3f + k * 3, v);
3049 qglVertex3f(v[0], v[1], v[2]);
3050 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
3051 qglVertex3f(v[0], v[1], v[2]);
3057 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3058 qglEnable(GL_CULL_FACE);
3061 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3063 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3067 texture = surface->texture;
3068 if (texture->basematerialflags & MATERIALFLAG_SKY)
3069 return; // transparent sky is too difficult
3070 R_UpdateTextureInfo(ent, texture);
3072 R_Mesh_Matrix(&ent->matrix);
3073 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3074 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3077 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
3079 int texturesurfaceindex;
3080 const msurface_t *surface;
3081 vec3_t tempcenter, center;
3082 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3084 // drawing sky transparently would be too difficult
3085 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3087 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3089 surface = texturesurfacelist[texturesurfaceindex];
3090 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3091 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3092 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3093 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3094 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3099 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3102 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3103 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3105 int i, j, f, flagsmask;
3106 int counttriangles = 0;
3107 msurface_t *surface, **surfacechain;
3108 texture_t *t, *texture;
3109 model_t *model = ent->model;
3111 const int maxsurfacelist = 1024;
3112 int numsurfacelist = 0;
3113 const msurface_t *surfacelist[1024];
3116 R_Mesh_Matrix(&ent->matrix);
3117 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3119 // update light styles
3120 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3122 for (i = 0;i < model->brushq1.light_styles;i++)
3124 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3126 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3127 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3128 for (;(surface = *surfacechain);surfacechain++)
3129 surface->cached_dlight = true;
3134 R_UpdateAllTextureInfo(ent);
3135 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3140 if (ent == r_refdef.worldentity)
3142 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3144 if (!r_worldsurfacevisible[j])
3146 if (t != surface->texture)
3150 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3153 t = surface->texture;
3154 texture = t->currentframe;
3155 f = texture->currentmaterialflags & flagsmask;
3157 if (f && surface->num_triangles)
3159 // if lightmap parameters changed, rebuild lightmap texture
3160 if (surface->cached_dlight)
3161 R_BuildLightMap(ent, surface);
3162 // add face to draw list
3163 surfacelist[numsurfacelist++] = surface;
3164 counttriangles += surface->num_triangles;
3165 if (numsurfacelist >= maxsurfacelist)
3167 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3175 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3177 if (t != surface->texture)
3181 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3184 t = surface->texture;
3185 texture = t->currentframe;
3186 f = texture->currentmaterialflags & flagsmask;
3188 if (f && surface->num_triangles)
3190 // if lightmap parameters changed, rebuild lightmap texture
3191 if (surface->cached_dlight)
3192 R_BuildLightMap(ent, surface);
3193 // add face to draw list
3194 surfacelist[numsurfacelist++] = surface;
3195 counttriangles += surface->num_triangles;
3196 if (numsurfacelist >= maxsurfacelist)
3198 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3205 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3206 if (!r_showtrispass)
3207 renderstats.entities_triangles += counttriangles;
3208 if (gl_support_fragment_shader)
3209 qglUseProgramObjectARB(0);