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 " //color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
669 "#ifdef USESPECULAR\n"
670 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
671 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
677 "#elif defined(MODE_LIGHTDIRECTIONMAP)\n"
678 " // deluxemap lightmapping\n"
680 " // get the surface normal and light normal\n"
681 "#ifdef SURFACENORMALIZE\n"
682 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
683 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)));\n"
685 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
686 " myhvec3 diffusenormal = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap));\n"
689 " // calculate directional shading\n"
690 " myhvec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0)));\n"
691 "#ifdef USESPECULAR\n"
692 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
693 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
696 " // apply lightmap color\n"
697 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * myhvec3(AmbientScale);\n"
702 "#else // MODE none (lightmap)\n"
703 " // apply lightmap color\n"
704 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
708 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord));\n"
713 " myhalf fog = texture2D(Texture_FogMask, myhvec2(length(EyeVector)*FogRangeRecip, 0.0)).x;\n"
714 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
717 " gl_FragColor = color * gl_Color;\n"
719 "#endif // !USEEASTEREGG\n"
724 // the loaded GLSL shader file for compiling shader permutations as needed
725 static char *shaderstring = NULL;
727 void R_GLSL_CompilePermutation(int permutation)
729 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
730 int vertstrings_count;
731 int fragstrings_count;
732 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
733 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
734 char permutationname[256];
738 vertstrings_list[0] = "#define VERTEX_SHADER\n";
739 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
740 vertstrings_count = 1;
741 fragstrings_count = 1;
742 permutationname[0] = 0;
743 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
745 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
746 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
747 strlcat(permutationname, " lightsource", sizeof(permutationname));
749 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP)
751 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP\n";
752 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP\n";
753 strlcat(permutationname, " lightdirectionmap", sizeof(permutationname));
755 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
757 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
758 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
759 strlcat(permutationname, " lightdirection", sizeof(permutationname));
761 if (permutation & SHADERPERMUTATION_GLOW)
763 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
764 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
765 strlcat(permutationname, " glow", sizeof(permutationname));
767 if (permutation & SHADERPERMUTATION_COLORMAPPING)
769 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
770 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
771 strlcat(permutationname, " colormapping", sizeof(permutationname));
773 if (permutation & SHADERPERMUTATION_SPECULAR)
775 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
776 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
777 strlcat(permutationname, " specular", sizeof(permutationname));
779 if (permutation & SHADERPERMUTATION_FOG)
781 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
782 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
783 strlcat(permutationname, " fog", sizeof(permutationname));
785 if (permutation & SHADERPERMUTATION_CUBEFILTER)
787 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
788 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
789 strlcat(permutationname, " cubefilter", sizeof(permutationname));
791 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
793 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
794 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
795 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
797 if (permutation & SHADERPERMUTATION_SURFACENORMALIZE)
799 vertstrings_list[vertstrings_count++] = "#define SURFACENORMALIZE\n";
800 fragstrings_list[fragstrings_count++] = "#define SURFACENORMALIZE\n";
801 strlcat(permutationname, " surfacenormalize", sizeof(permutationname));
803 if (permutation & SHADERPERMUTATION_GEFORCEFX)
805 vertstrings_list[vertstrings_count++] = "#define GEFORCEFX\n";
806 fragstrings_list[fragstrings_count++] = "#define GEFORCEFX\n";
807 strlcat(permutationname, " halffloat", sizeof(permutationname));
811 vertstrings_list[vertstrings_count++] = shaderstring;
812 fragstrings_list[fragstrings_count++] = shaderstring;
816 vertstrings_list[vertstrings_count++] = builtinshaderstring;
817 fragstrings_list[fragstrings_count++] = builtinshaderstring;
819 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
823 qglUseProgramObjectARB(p->program);
824 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
825 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
826 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
827 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
828 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
829 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
830 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
831 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
832 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
833 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
834 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
835 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
836 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
837 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
838 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
839 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
840 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
841 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
842 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
843 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
844 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
845 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
846 p->loc_OffsetMapping_Bias = qglGetUniformLocationARB(p->program, "OffsetMapping_Bias");
847 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
848 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
849 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
850 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
851 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
852 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
853 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
854 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
855 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
856 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
857 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
858 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
859 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
860 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
861 qglUseProgramObjectARB(0);
865 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
868 void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting)
870 // select a permutation of the lighting shader appropriate to this
871 // combination of texture, entity, light source, and fogging, only use the
872 // minimum features necessary to avoid wasting rendering time in the
873 // fragment shader on features that are not being used
875 float specularscale = texture->specularscale;
876 r_glsl_permutation = NULL;
877 if (r_shadow_rtlight)
879 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
880 specularscale *= r_shadow_rtlight->specularscale;
881 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
882 permutation |= SHADERPERMUTATION_CUBEFILTER;
884 else if (modellighting)
886 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
887 if (texture->skin.glow)
888 permutation |= SHADERPERMUTATION_GLOW;
890 else if (r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
892 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP;
893 if (texture->skin.glow)
894 permutation |= SHADERPERMUTATION_GLOW;
898 if (texture->skin.glow)
899 permutation |= SHADERPERMUTATION_GLOW;
901 if (specularscale > 0)
902 permutation |= SHADERPERMUTATION_SPECULAR;
904 permutation |= SHADERPERMUTATION_FOG;
905 if (texture->colormapping)
906 permutation |= SHADERPERMUTATION_COLORMAPPING;
907 if (r_glsl_offsetmapping.integer)
908 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
909 if (r_glsl_surfacenormalize.integer)
910 permutation |= SHADERPERMUTATION_SURFACENORMALIZE;
911 if (r_glsl_usehalffloat.integer)
912 permutation |= SHADERPERMUTATION_GEFORCEFX;
913 if (!r_glsl_permutations[permutation].program)
915 if (!r_glsl_permutations[permutation].compiled)
916 R_GLSL_CompilePermutation(permutation);
917 if (!r_glsl_permutations[permutation].program)
919 // remove features until we find a valid permutation
921 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
923 // reduce i more quickly whenever it would not remove any bits
927 if (!r_glsl_permutations[permutation].compiled)
928 R_GLSL_CompilePermutation(permutation);
929 if (r_glsl_permutations[permutation].program)
932 return; // utterly failed
936 r_glsl_permutation = r_glsl_permutations + permutation;
938 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
939 R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
940 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
942 R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
943 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
944 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]);
945 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
946 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
947 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
948 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
950 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
952 if (texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
954 if (r_glsl_permutation->loc_AmbientColor >= 0)
955 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, 1, 1, 1);
956 if (r_glsl_permutation->loc_DiffuseColor >= 0)
957 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, 0, 0, 0);
958 if (r_glsl_permutation->loc_SpecularColor >= 0)
959 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, 0, 0, 0);
960 if (r_glsl_permutation->loc_LightDir >= 0)
961 qglUniform3fARB(r_glsl_permutation->loc_LightDir, 0, 0, -1);
965 if (r_glsl_permutation->loc_AmbientColor >= 0)
966 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
967 if (r_glsl_permutation->loc_DiffuseColor >= 0)
968 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
969 if (r_glsl_permutation->loc_SpecularColor >= 0)
970 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
971 if (r_glsl_permutation->loc_LightDir >= 0)
972 qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->modellight_lightdir[2]);
977 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
978 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
979 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale * 2.0f);
981 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(texture->skin.nmap));
982 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
983 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
984 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
985 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
986 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
987 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
988 if (r_glsl_permutation->loc_FogColor >= 0)
990 // additive passes are only darkened by fog, not tinted
991 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
992 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
994 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
996 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
997 if (r_glsl_permutation->loc_Color_Pants >= 0)
999 if (texture->skin.pants)
1000 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
1002 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1004 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1006 if (texture->skin.shirt)
1007 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
1009 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1011 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
1012 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
1013 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1014 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Bias, r_glsl_offsetmapping_bias.value);
1018 void gl_main_start(void)
1020 // use half float math where available (speed gain on NVIDIA GFFX and GF6)
1021 if (gl_support_half_float)
1022 Cvar_SetValue("r_glsl_usehalffloat", 1);
1023 r_main_texturepool = R_AllocTexturePool();
1024 r_bloom_texture_screen = NULL;
1025 r_bloom_texture_bloom = NULL;
1026 R_BuildBlankTextures();
1028 if (gl_texturecubemap)
1031 R_BuildNormalizationCube();
1033 R_BuildFogTexture();
1034 shaderstring = NULL;
1035 if (gl_support_fragment_shader)
1037 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
1039 Con_Printf("GLSL shader text loaded from disk\n");
1040 // if we couldn't load the shader file, fall back to builtin shader
1044 Con_Printf("GLSL shader text loaded from fallback\n");
1045 shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1046 strcpy(shaderstring, builtinshaderstring);
1050 Con_Printf("GLSL shader text loaded\n");
1051 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1054 void gl_main_shutdown(void)
1057 R_FreeTexturePool(&r_main_texturepool);
1058 r_bloom_texture_screen = NULL;
1059 r_bloom_texture_bloom = NULL;
1060 r_texture_blanknormalmap = NULL;
1061 r_texture_white = NULL;
1062 r_texture_black = NULL;
1063 r_texture_whitecube = NULL;
1064 r_texture_normalizationcube = NULL;
1066 Mem_Free(shaderstring);
1067 shaderstring = NULL;
1068 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1069 if (r_glsl_permutations[i].program)
1070 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
1071 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1074 extern void CL_ParseEntityLump(char *entitystring);
1075 void gl_main_newmap(void)
1077 // FIXME: move this code to client
1079 char *entities, entname[MAX_QPATH];
1083 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1084 l = (int)strlen(entname) - 4;
1085 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1087 strcpy(entname + l, ".ent");
1088 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1090 CL_ParseEntityLump(entities);
1095 if (cl.worldmodel->brush.entities)
1096 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1100 void GL_Main_Init(void)
1102 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1104 FOG_registercvars(); // FIXME: move this fog stuff to client?
1105 Cvar_RegisterVariable(&r_nearclip);
1106 Cvar_RegisterVariable(&r_showtris);
1107 Cvar_RegisterVariable(&r_showtris_polygonoffset);
1108 Cvar_RegisterVariable(&r_shownormals);
1109 Cvar_RegisterVariable(&r_showlighting);
1110 Cvar_RegisterVariable(&r_showshadowvolumes);
1111 Cvar_RegisterVariable(&r_showcollisionbrushes);
1112 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1113 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1114 Cvar_RegisterVariable(&r_showdisabledepthtest);
1115 Cvar_RegisterVariable(&r_drawentities);
1116 Cvar_RegisterVariable(&r_drawviewmodel);
1117 Cvar_RegisterVariable(&r_speeds);
1118 Cvar_RegisterVariable(&r_fullbrights);
1119 Cvar_RegisterVariable(&r_wateralpha);
1120 Cvar_RegisterVariable(&r_dynamic);
1121 Cvar_RegisterVariable(&r_fullbright);
1122 Cvar_RegisterVariable(&r_textureunits);
1123 Cvar_RegisterVariable(&r_glsl);
1124 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1125 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1126 Cvar_RegisterVariable(&r_glsl_offsetmapping_bias);
1127 Cvar_RegisterVariable(&r_glsl_usehalffloat);
1128 Cvar_RegisterVariable(&r_glsl_surfacenormalize);
1129 Cvar_RegisterVariable(&r_lerpsprites);
1130 Cvar_RegisterVariable(&r_lerpmodels);
1131 Cvar_RegisterVariable(&r_waterscroll);
1132 Cvar_RegisterVariable(&r_bloom);
1133 Cvar_RegisterVariable(&r_bloom_intensity);
1134 Cvar_RegisterVariable(&r_bloom_blur);
1135 Cvar_RegisterVariable(&r_bloom_resolution);
1136 Cvar_RegisterVariable(&r_bloom_power);
1137 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1138 Cvar_RegisterVariable(&developer_texturelogging);
1139 Cvar_RegisterVariable(&gl_lightmaps);
1140 Cvar_RegisterVariable(&r_test);
1141 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1142 Cvar_SetValue("r_fullbrights", 0);
1143 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1146 static vec3_t r_farclip_origin;
1147 static vec3_t r_farclip_direction;
1148 static vec_t r_farclip_directiondist;
1149 static vec_t r_farclip_meshfarclip;
1150 static int r_farclip_directionbit0;
1151 static int r_farclip_directionbit1;
1152 static int r_farclip_directionbit2;
1154 // enlarge farclip to accomodate box
1155 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1158 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1159 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1160 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1161 if (r_farclip_meshfarclip < d)
1162 r_farclip_meshfarclip = d;
1165 // return farclip value
1166 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1170 VectorCopy(origin, r_farclip_origin);
1171 VectorCopy(direction, r_farclip_direction);
1172 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1173 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1174 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1175 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1176 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1178 if (r_refdef.worldmodel)
1179 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1180 for (i = 0;i < r_refdef.numentities;i++)
1181 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1183 return r_farclip_meshfarclip - r_farclip_directiondist;
1186 extern void R_Textures_Init(void);
1187 extern void GL_Draw_Init(void);
1188 extern void GL_Main_Init(void);
1189 extern void R_Shadow_Init(void);
1190 extern void R_Sky_Init(void);
1191 extern void GL_Surf_Init(void);
1192 extern void R_Crosshairs_Init(void);
1193 extern void R_Light_Init(void);
1194 extern void R_Particles_Init(void);
1195 extern void R_Explosion_Init(void);
1196 extern void gl_backend_init(void);
1197 extern void Sbar_Init(void);
1198 extern void R_LightningBeams_Init(void);
1199 extern void Mod_RenderInit(void);
1201 void Render_Init(void)
1211 R_Crosshairs_Init();
1216 R_LightningBeams_Init();
1225 extern char *ENGINE_EXTENSIONS;
1228 VID_CheckExtensions();
1230 // LordHavoc: report supported extensions
1231 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1233 // clear to black (loading plaque will be seen over this)
1234 qglClearColor(0,0,0,1);
1235 qglClear(GL_COLOR_BUFFER_BIT);
1238 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1242 for (i = 0;i < 4;i++)
1249 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1253 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1257 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1261 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1265 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1269 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1273 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1277 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1285 //==================================================================================
1287 static void R_UpdateEntityLighting(entity_render_t *ent)
1289 vec3_t tempdiffusenormal;
1290 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));
1291 VectorClear(ent->modellight_diffuse);
1292 VectorClear(ent->modellight_lightdir);
1293 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1294 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1296 VectorSet(ent->modellight_ambient, 1, 1, 1);
1297 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1298 VectorNormalize(ent->modellight_lightdir);
1299 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1300 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1301 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1302 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1303 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1304 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1307 static void R_MarkEntities (void)
1310 entity_render_t *ent;
1312 if (!r_drawentities.integer)
1315 r_refdef.worldentity->visframe = r_framecount;
1316 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1317 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1319 // worldmodel can check visibility
1320 for (i = 0;i < r_refdef.numentities;i++)
1322 ent = r_refdef.entities[i];
1323 // some of the renderer still relies on origin...
1324 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1325 // some of the renderer still relies on scale...
1326 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1327 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)))
1329 ent->visframe = r_framecount;
1330 R_UpdateEntityLighting(ent);
1336 // no worldmodel or it can't check visibility
1337 for (i = 0;i < r_refdef.numentities;i++)
1339 ent = r_refdef.entities[i];
1340 // some of the renderer still relies on origin...
1341 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1342 // some of the renderer still relies on scale...
1343 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1344 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1346 ent->visframe = r_framecount;
1347 R_UpdateEntityLighting(ent);
1353 // only used if skyrendermasked, and normally returns false
1354 int R_DrawBrushModelsSky (void)
1357 entity_render_t *ent;
1359 if (!r_drawentities.integer)
1363 for (i = 0;i < r_refdef.numentities;i++)
1365 ent = r_refdef.entities[i];
1366 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1368 ent->model->DrawSky(ent);
1375 void R_DrawNoModel(entity_render_t *ent);
1376 void R_DrawModels(void)
1379 entity_render_t *ent;
1381 if (!r_drawentities.integer)
1384 for (i = 0;i < r_refdef.numentities;i++)
1386 ent = r_refdef.entities[i];
1387 if (ent->visframe == r_framecount)
1389 renderstats.entities++;
1390 if (ent->model && ent->model->Draw != NULL)
1391 ent->model->Draw(ent);
1398 static void R_SetFrustum(void)
1400 // break apart the view matrix into vectors for various purposes
1401 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1402 VectorNegate(r_viewleft, r_viewright);
1405 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1406 frustum[0].normal[1] = 0 - 0;
1407 frustum[0].normal[2] = -1 - 0;
1408 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1409 frustum[1].normal[1] = 0 + 0;
1410 frustum[1].normal[2] = -1 + 0;
1411 frustum[2].normal[0] = 0 - 0;
1412 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1413 frustum[2].normal[2] = -1 - 0;
1414 frustum[3].normal[0] = 0 + 0;
1415 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1416 frustum[3].normal[2] = -1 + 0;
1420 zNear = r_nearclip.value;
1421 nudge = 1.0 - 1.0 / (1<<23);
1422 frustum[4].normal[0] = 0 - 0;
1423 frustum[4].normal[1] = 0 - 0;
1424 frustum[4].normal[2] = -1 - -nudge;
1425 frustum[4].dist = 0 - -2 * zNear * nudge;
1426 frustum[5].normal[0] = 0 + 0;
1427 frustum[5].normal[1] = 0 + 0;
1428 frustum[5].normal[2] = -1 + -nudge;
1429 frustum[5].dist = 0 + -2 * zNear * nudge;
1435 frustum[0].normal[0] = m[3] - m[0];
1436 frustum[0].normal[1] = m[7] - m[4];
1437 frustum[0].normal[2] = m[11] - m[8];
1438 frustum[0].dist = m[15] - m[12];
1440 frustum[1].normal[0] = m[3] + m[0];
1441 frustum[1].normal[1] = m[7] + m[4];
1442 frustum[1].normal[2] = m[11] + m[8];
1443 frustum[1].dist = m[15] + m[12];
1445 frustum[2].normal[0] = m[3] - m[1];
1446 frustum[2].normal[1] = m[7] - m[5];
1447 frustum[2].normal[2] = m[11] - m[9];
1448 frustum[2].dist = m[15] - m[13];
1450 frustum[3].normal[0] = m[3] + m[1];
1451 frustum[3].normal[1] = m[7] + m[5];
1452 frustum[3].normal[2] = m[11] + m[9];
1453 frustum[3].dist = m[15] + m[13];
1455 frustum[4].normal[0] = m[3] - m[2];
1456 frustum[4].normal[1] = m[7] - m[6];
1457 frustum[4].normal[2] = m[11] - m[10];
1458 frustum[4].dist = m[15] - m[14];
1460 frustum[5].normal[0] = m[3] + m[2];
1461 frustum[5].normal[1] = m[7] + m[6];
1462 frustum[5].normal[2] = m[11] + m[10];
1463 frustum[5].dist = m[15] + m[14];
1468 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1469 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1470 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1471 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1472 VectorCopy(r_viewforward, frustum[4].normal);
1473 VectorNormalize(frustum[0].normal);
1474 VectorNormalize(frustum[1].normal);
1475 VectorNormalize(frustum[2].normal);
1476 VectorNormalize(frustum[3].normal);
1477 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1478 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1479 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1480 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1481 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1482 PlaneClassify(&frustum[0]);
1483 PlaneClassify(&frustum[1]);
1484 PlaneClassify(&frustum[2]);
1485 PlaneClassify(&frustum[3]);
1486 PlaneClassify(&frustum[4]);
1488 // LordHavoc: note to all quake engine coders, Quake had a special case
1489 // for 90 degrees which assumed a square view (wrong), so I removed it,
1490 // Quake2 has it disabled as well.
1492 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1493 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1494 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1495 //PlaneClassify(&frustum[0]);
1497 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1498 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1499 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1500 //PlaneClassify(&frustum[1]);
1502 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1503 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1504 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1505 //PlaneClassify(&frustum[2]);
1507 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1508 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1509 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1510 //PlaneClassify(&frustum[3]);
1513 //VectorCopy(r_viewforward, frustum[4].normal);
1514 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1515 //PlaneClassify(&frustum[4]);
1518 static void R_BlendView(void)
1520 int screenwidth, screenheight;
1525 // set the (poorly named) screenwidth and screenheight variables to
1526 // a power of 2 at least as large as the screen, these will define the
1527 // size of the texture to allocate
1528 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1529 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1531 doblend = r_refdef.viewblend[3] >= 0.01f;
1532 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;
1534 if (!dobloom && !doblend)
1537 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1539 GL_DepthTest(false);
1540 R_Mesh_Matrix(&identitymatrix);
1541 // vertex coordinates for a quad that covers the screen exactly
1542 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
1543 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
1544 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
1545 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
1548 int bloomwidth, bloomheight, x, dobloomblend, range;
1549 float xoffset, yoffset, r;
1550 renderstats.bloom++;
1551 // allocate textures as needed
1552 if (!r_bloom_texture_screen)
1553 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1554 if (!r_bloom_texture_bloom)
1555 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1556 // set bloomwidth and bloomheight to the bloom resolution that will be
1557 // used (often less than the screen resolution for faster rendering)
1558 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1559 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1560 // set up a texcoord array for the full resolution screen image
1561 // (we have to keep this around to copy back during final render)
1562 varray_texcoord2f[0][0] = 0;
1563 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1564 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1565 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1566 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1567 varray_texcoord2f[0][5] = 0;
1568 varray_texcoord2f[0][6] = 0;
1569 varray_texcoord2f[0][7] = 0;
1570 // set up a texcoord array for the reduced resolution bloom image
1571 // (which will be additive blended over the screen image)
1572 varray_texcoord2f[1][0] = 0;
1573 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1574 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1575 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1576 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1577 varray_texcoord2f[1][5] = 0;
1578 varray_texcoord2f[1][6] = 0;
1579 varray_texcoord2f[1][7] = 0;
1580 memset(&m, 0, sizeof(m));
1581 m.pointer_vertex = varray_vertex3f;
1582 m.pointer_texcoord[0] = varray_texcoord2f[0];
1583 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1585 // copy view into the full resolution screen image texture
1586 GL_ActiveTexture(0);
1587 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1588 renderstats.bloom_copypixels += r_view_width * r_view_height;
1589 // now scale it down to the bloom size and raise to a power of itself
1590 // to darken it (this leaves the really bright stuff bright, and
1591 // everything else becomes very dark)
1592 // TODO: optimize with multitexture or GLSL
1593 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1594 GL_BlendFunc(GL_ONE, GL_ZERO);
1595 GL_Color(1, 1, 1, 1);
1596 R_Mesh_Draw(0, 4, 2, polygonelements);
1597 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1598 // render multiple times with a multiply blendfunc to raise to a power
1599 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1600 for (x = 1;x < r_bloom_power.integer;x++)
1602 R_Mesh_Draw(0, 4, 2, polygonelements);
1603 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1605 // we now have a darkened bloom image in the framebuffer, copy it into
1606 // the bloom image texture for more processing
1607 memset(&m, 0, sizeof(m));
1608 m.pointer_vertex = varray_vertex3f;
1609 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1610 m.pointer_texcoord[0] = varray_texcoord2f[2];
1612 GL_ActiveTexture(0);
1613 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1614 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1615 // blend on at multiple vertical offsets to achieve a vertical blur
1616 // TODO: do offset blends using GLSL
1617 range = r_bloom_blur.integer * bloomwidth / 320;
1618 GL_BlendFunc(GL_ONE, GL_ZERO);
1619 for (x = -range;x <= range;x++)
1621 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1622 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1623 // compute a texcoord array with the specified x and y offset
1624 varray_texcoord2f[2][0] = xoffset+0;
1625 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1626 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1627 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1628 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1629 varray_texcoord2f[2][5] = yoffset+0;
1630 varray_texcoord2f[2][6] = xoffset+0;
1631 varray_texcoord2f[2][7] = yoffset+0;
1632 // this r value looks like a 'dot' particle, fading sharply to
1633 // black at the edges
1634 // (probably not realistic but looks good enough)
1635 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1638 GL_Color(r, r, r, 1);
1639 R_Mesh_Draw(0, 4, 2, polygonelements);
1640 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1641 GL_BlendFunc(GL_ONE, GL_ONE);
1643 // copy the vertically blurred bloom view to a texture
1644 GL_ActiveTexture(0);
1645 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1646 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1647 // blend the vertically blurred image at multiple offsets horizontally
1648 // to finish the blur effect
1649 // TODO: do offset blends using GLSL
1650 range = r_bloom_blur.integer * bloomwidth / 320;
1651 GL_BlendFunc(GL_ONE, GL_ZERO);
1652 for (x = -range;x <= range;x++)
1654 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1655 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1656 // compute a texcoord array with the specified x and y offset
1657 varray_texcoord2f[2][0] = xoffset+0;
1658 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1659 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1660 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1661 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1662 varray_texcoord2f[2][5] = yoffset+0;
1663 varray_texcoord2f[2][6] = xoffset+0;
1664 varray_texcoord2f[2][7] = yoffset+0;
1665 // this r value looks like a 'dot' particle, fading sharply to
1666 // black at the edges
1667 // (probably not realistic but looks good enough)
1668 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1671 GL_Color(r, r, r, 1);
1672 R_Mesh_Draw(0, 4, 2, polygonelements);
1673 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1674 GL_BlendFunc(GL_ONE, GL_ONE);
1676 // copy the blurred bloom view to a texture
1677 GL_ActiveTexture(0);
1678 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1679 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1680 // go back to full view area
1681 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1682 // put the original screen image back in place and blend the bloom
1684 memset(&m, 0, sizeof(m));
1685 m.pointer_vertex = varray_vertex3f;
1686 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1687 m.pointer_texcoord[0] = varray_texcoord2f[0];
1689 dobloomblend = false;
1691 // do both in one pass if possible
1692 if (r_textureunits.integer >= 2 && gl_combine.integer)
1694 dobloomblend = false;
1695 m.texcombinergb[1] = GL_ADD;
1696 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1697 m.pointer_texcoord[1] = varray_texcoord2f[1];
1700 dobloomblend = true;
1703 GL_BlendFunc(GL_ONE, GL_ZERO);
1705 R_Mesh_Draw(0, 4, 2, polygonelements);
1706 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1707 // now blend on the bloom texture if multipass
1710 memset(&m, 0, sizeof(m));
1711 m.pointer_vertex = varray_vertex3f;
1712 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1713 m.pointer_texcoord[0] = varray_texcoord2f[1];
1715 GL_BlendFunc(GL_ONE, GL_ONE);
1717 R_Mesh_Draw(0, 4, 2, polygonelements);
1718 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1723 // apply a color tint to the whole view
1724 memset(&m, 0, sizeof(m));
1725 m.pointer_vertex = varray_vertex3f;
1727 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1728 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1729 R_Mesh_Draw(0, 4, 2, polygonelements);
1733 void R_RenderScene(void);
1735 matrix4x4_t r_waterscrollmatrix;
1742 void R_RenderView(void)
1744 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1745 return; //Host_Error ("R_RenderView: NULL worldmodel");
1747 r_view_width = bound(0, r_refdef.width, vid.width);
1748 r_view_height = bound(0, r_refdef.height, vid.height);
1750 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1751 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1753 r_view_matrix = r_refdef.viewentitymatrix;
1754 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1755 r_rtworld = r_shadow_realtime_world.integer;
1756 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1757 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1758 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1759 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1761 // GL is weird because it's bottom to top, r_view_y is top to bottom
1762 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1763 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1764 GL_ScissorTest(true);
1769 if (r_timereport_active)
1770 R_TimeReport("setup");
1772 qglDepthFunc(GL_LEQUAL);
1773 qglPolygonOffset(0, 0);
1774 qglEnable(GL_POLYGON_OFFSET_FILL);
1778 qglPolygonOffset(0, 0);
1779 qglDisable(GL_POLYGON_OFFSET_FILL);
1782 if (r_timereport_active)
1783 R_TimeReport("blendview");
1785 GL_Scissor(0, 0, vid.width, vid.height);
1786 GL_ScissorTest(false);
1790 void CSQC_R_ClearScreen (void)
1792 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1793 return; //Host_Error ("R_RenderView: NULL worldmodel");
1795 r_view_width = bound(0, r_refdef.width, vid.width);
1796 r_view_height = bound(0, r_refdef.height, vid.height);
1798 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1799 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1801 r_view_matrix = r_refdef.viewentitymatrix;
1802 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1803 r_rtworld = r_shadow_realtime_world.integer;
1804 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1805 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1806 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1807 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1809 // GL is weird because it's bottom to top, r_view_y is top to bottom
1810 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1811 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1812 GL_ScissorTest(true);
1817 if (r_timereport_active)
1818 R_TimeReport("setup");
1822 void CSQC_R_RenderScene (void)
1824 qglDepthFunc(GL_LEQUAL);
1825 qglPolygonOffset(0, 0);
1826 qglEnable(GL_POLYGON_OFFSET_FILL);
1830 qglPolygonOffset(0, 0);
1831 qglDisable(GL_POLYGON_OFFSET_FILL);
1834 if (r_timereport_active)
1835 R_TimeReport("blendview");
1837 GL_Scissor(0, 0, vid.width, vid.height);
1838 GL_ScissorTest(false);
1841 extern void R_DrawLightningBeams (void);
1842 extern void VM_AddPolygonsToMeshQueue (void);
1843 void R_RenderScene(void)
1847 // don't let sound skip if going slow
1848 if (r_refdef.extraupdate)
1853 if (gl_support_fragment_shader)
1854 qglUseProgramObjectARB(0);
1856 R_MeshQueue_BeginScene();
1860 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1861 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1863 if (r_rtworldshadows || r_rtdlightshadows)
1864 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1866 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1868 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1870 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);
1874 R_WorldVisibility();
1875 if (r_timereport_active)
1876 R_TimeReport("worldvis");
1879 if (r_timereport_active)
1880 R_TimeReport("markentity");
1882 R_Shadow_UpdateWorldLightSelection();
1884 for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1890 GL_BlendFunc(GL_ONE, GL_ONE);
1891 GL_DepthTest(!r_showdisabledepthtest.integer);
1892 GL_DepthMask(GL_FALSE);
1893 memset(&m, 0, sizeof(m));
1895 //qglEnable(GL_LINE_SMOOTH);
1896 qglEnable(GL_POLYGON_OFFSET_LINE);
1897 qglPolygonOffset(0, r_showtris_polygonoffset.value);
1901 if (cl.csqc_vidvars.drawworld)
1903 // don't let sound skip if going slow
1904 if (r_refdef.extraupdate)
1908 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1909 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1911 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1912 if (r_timereport_active)
1913 R_TimeReport("worldsky");
1916 if (R_DrawBrushModelsSky() && r_timereport_active)
1917 R_TimeReport("bmodelsky");
1920 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1921 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1923 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1924 if (r_timereport_active)
1925 R_TimeReport("world");
1929 // don't let sound skip if going slow
1930 if (r_refdef.extraupdate)
1934 GL_ShowTrisColor(0, 0.015, 0, 1);
1937 if (r_timereport_active)
1938 R_TimeReport("models");
1940 // don't let sound skip if going slow
1941 if (r_refdef.extraupdate)
1945 GL_ShowTrisColor(0, 0, 0.033, 1);
1946 R_ShadowVolumeLighting(false);
1947 if (r_timereport_active)
1948 R_TimeReport("rtlights");
1950 // don't let sound skip if going slow
1951 if (r_refdef.extraupdate)
1955 GL_ShowTrisColor(0.1, 0, 0, 1);
1957 if (cl.csqc_vidvars.drawworld)
1959 R_DrawLightningBeams();
1960 if (r_timereport_active)
1961 R_TimeReport("lightning");
1964 if (r_timereport_active)
1965 R_TimeReport("particles");
1968 if (r_timereport_active)
1969 R_TimeReport("explosions");
1972 R_MeshQueue_RenderTransparent();
1973 if (r_timereport_active)
1974 R_TimeReport("drawtrans");
1976 if (cl.csqc_vidvars.drawworld)
1979 if (r_timereport_active)
1980 R_TimeReport("coronas");
1982 if(cl.csqc_vidvars.drawcrosshair)
1984 R_DrawWorldCrosshair();
1985 if (r_timereport_active)
1986 R_TimeReport("crosshair");
1989 VM_AddPolygonsToMeshQueue();
1991 R_MeshQueue_Render();
1995 //qglDisable(GL_LINE_SMOOTH);
1996 qglDisable(GL_POLYGON_OFFSET_LINE);
2002 R_MeshQueue_EndScene();
2004 // don't let sound skip if going slow
2005 if (r_refdef.extraupdate)
2008 if (gl_support_fragment_shader)
2009 qglUseProgramObjectARB(0);
2013 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2016 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2018 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2019 GL_DepthMask(false);
2021 R_Mesh_Matrix(&identitymatrix);
2023 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2024 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2025 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2026 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2027 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2028 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2029 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2030 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2031 R_FillColors(color, 8, cr, cg, cb, ca);
2034 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2036 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
2038 c[0] = c[0] * f1 + fogcolor[0] * f2;
2039 c[1] = c[1] * f1 + fogcolor[1] * f2;
2040 c[2] = c[2] * f1 + fogcolor[2] * f2;
2043 memset(&m, 0, sizeof(m));
2044 m.pointer_vertex = vertex3f;
2045 m.pointer_color = color;
2051 int nomodelelements[24] =
2063 float nomodelvertex3f[6*3] =
2073 float nomodelcolor4f[6*4] =
2075 0.0f, 0.0f, 0.5f, 1.0f,
2076 0.0f, 0.0f, 0.5f, 1.0f,
2077 0.0f, 0.5f, 0.0f, 1.0f,
2078 0.0f, 0.5f, 0.0f, 1.0f,
2079 0.5f, 0.0f, 0.0f, 1.0f,
2080 0.5f, 0.0f, 0.0f, 1.0f
2083 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2089 R_Mesh_Matrix(&ent->matrix);
2091 memset(&m, 0, sizeof(m));
2092 m.pointer_vertex = nomodelvertex3f;
2094 if (ent->flags & EF_ADDITIVE)
2096 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2097 GL_DepthMask(false);
2099 else if (ent->alpha < 1)
2101 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2102 GL_DepthMask(false);
2106 GL_BlendFunc(GL_ONE, GL_ZERO);
2109 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2112 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2113 m.pointer_color = color4f;
2114 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2116 for (i = 0, c = color4f;i < 6;i++, c += 4)
2118 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2119 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2120 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2124 else if (ent->alpha != 1)
2126 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2127 m.pointer_color = color4f;
2128 for (i = 0, c = color4f;i < 6;i++, c += 4)
2132 m.pointer_color = nomodelcolor4f;
2134 R_Mesh_Draw(0, 6, 8, nomodelelements);
2137 void R_DrawNoModel(entity_render_t *ent)
2139 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2140 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2142 // R_DrawNoModelCallback(ent, 0);
2145 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2147 vec3_t right1, right2, diff, normal;
2149 VectorSubtract (org2, org1, normal);
2151 // calculate 'right' vector for start
2152 VectorSubtract (r_vieworigin, org1, diff);
2153 CrossProduct (normal, diff, right1);
2154 VectorNormalize (right1);
2156 // calculate 'right' vector for end
2157 VectorSubtract (r_vieworigin, org2, diff);
2158 CrossProduct (normal, diff, right2);
2159 VectorNormalize (right2);
2161 vert[ 0] = org1[0] + width * right1[0];
2162 vert[ 1] = org1[1] + width * right1[1];
2163 vert[ 2] = org1[2] + width * right1[2];
2164 vert[ 3] = org1[0] - width * right1[0];
2165 vert[ 4] = org1[1] - width * right1[1];
2166 vert[ 5] = org1[2] - width * right1[2];
2167 vert[ 6] = org2[0] - width * right2[0];
2168 vert[ 7] = org2[1] - width * right2[1];
2169 vert[ 8] = org2[2] - width * right2[2];
2170 vert[ 9] = org2[0] + width * right2[0];
2171 vert[10] = org2[1] + width * right2[1];
2172 vert[11] = org2[2] + width * right2[2];
2175 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2177 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)
2179 float fog = 0.0f, ifog;
2183 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2186 R_Mesh_Matrix(&identitymatrix);
2187 GL_BlendFunc(blendfunc1, blendfunc2);
2188 GL_DepthMask(false);
2189 GL_DepthTest(!depthdisable);
2191 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2192 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2193 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2194 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2195 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2196 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2197 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2198 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2199 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2200 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2201 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2202 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2204 memset(&m, 0, sizeof(m));
2205 m.tex[0] = R_GetTexture(texture);
2206 m.pointer_texcoord[0] = spritetexcoord2f;
2207 m.pointer_vertex = varray_vertex3f;
2209 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2210 R_Mesh_Draw(0, 4, 2, polygonelements);
2212 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2214 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2215 GL_BlendFunc(blendfunc1, GL_ONE);
2216 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2217 R_Mesh_Draw(0, 4, 2, polygonelements);
2221 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2225 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2226 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2228 if (i == mesh->numvertices)
2230 if (mesh->numvertices < mesh->maxvertices)
2232 VectorCopy(v, vertex3f);
2233 mesh->numvertices++;
2235 return mesh->numvertices;
2241 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2245 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2246 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2247 e = mesh->element3i + mesh->numtriangles * 3;
2248 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2250 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2251 if (mesh->numtriangles < mesh->maxtriangles)
2256 mesh->numtriangles++;
2258 element[1] = element[2];
2262 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2264 int planenum, planenum2;
2267 mplane_t *plane, *plane2;
2268 float temppoints[2][256*3];
2269 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2273 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2274 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2276 if (planenum2 == planenum)
2278 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);
2281 if (tempnumpoints < 3)
2283 // generate elements forming a triangle fan for this polygon
2284 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2288 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)
2290 texturelayer_t *layer;
2291 layer = t->currentlayers + t->currentnumlayers++;
2293 layer->depthmask = depthmask;
2294 layer->blendfunc1 = blendfunc1;
2295 layer->blendfunc2 = blendfunc2;
2296 layer->texture = texture;
2297 layer->texmatrix = *matrix;
2298 layer->color[0] = r;
2299 layer->color[1] = g;
2300 layer->color[2] = b;
2301 layer->color[3] = a;
2304 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2306 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2307 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2310 texture_t *texture = t;
2311 model_t *model = ent->model;
2312 int s = ent->skinnum;
2313 if ((unsigned int)s >= (unsigned int)model->numskins)
2315 if (model->skinscenes)
2317 if (model->skinscenes[s].framecount > 1)
2318 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2320 s = model->skinscenes[s].firstframe;
2323 t = t + s * model->num_surfaces;
2325 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];
2326 texture->currentframe = t;
2329 t->currentmaterialflags = t->basematerialflags;
2330 t->currentalpha = ent->alpha;
2331 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2332 t->currentalpha *= r_wateralpha.value;
2333 if (!(ent->flags & RENDER_LIGHT))
2334 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2335 if (ent->effects & EF_ADDITIVE)
2336 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2337 else if (t->currentalpha < 1)
2338 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2339 if (ent->effects & EF_NODEPTHTEST)
2340 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2341 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2342 t->currenttexmatrix = r_waterscrollmatrix;
2344 t->currenttexmatrix = identitymatrix;
2346 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2347 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2348 t->glosstexture = r_texture_white;
2349 t->specularpower = 8;
2350 t->specularscale = 0;
2351 if (r_shadow_gloss.integer > 0)
2355 if (r_shadow_glossintensity.value > 0)
2357 t->glosstexture = t->skin.gloss;
2358 t->specularscale = r_shadow_glossintensity.value;
2361 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2362 t->specularscale = r_shadow_gloss2intensity.value;
2365 t->currentnumlayers = 0;
2366 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2368 if (gl_lightmaps.integer)
2369 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2370 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2372 int blendfunc1, blendfunc2, depthmask;
2373 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2375 blendfunc1 = GL_SRC_ALPHA;
2376 blendfunc2 = GL_ONE;
2379 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2381 blendfunc1 = GL_SRC_ALPHA;
2382 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2387 blendfunc1 = GL_ONE;
2388 blendfunc2 = GL_ZERO;
2391 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2393 rtexture_t *currentbasetexture;
2395 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2396 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2397 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2398 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2400 // fullbright is not affected by r_lightmapintensity
2401 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2402 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2403 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);
2404 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2405 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);
2411 // q3bsp has no lightmap updates, so the lightstylevalue that
2412 // would normally be baked into the lightmaptexture must be
2413 // applied to the color
2414 if (ent->model->type == mod_brushq3)
2415 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2416 colorscale *= r_lightmapintensity;
2417 if (r_textureunits.integer >= 2 && gl_combine.integer)
2418 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);
2419 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2420 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);
2422 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);
2423 if (r_ambient.value >= (1.0f/64.0f))
2424 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);
2425 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2427 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);
2428 if (r_ambient.value >= (1.0f/64.0f))
2429 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);
2431 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2433 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);
2434 if (r_ambient.value >= (1.0f/64.0f))
2435 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);
2438 if (t->skin.glow != NULL)
2439 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2440 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2442 // if this is opaque use alpha blend which will darken the earlier
2445 // if this is an alpha blended material, all the earlier passes
2446 // were darkened by fog already, so we only need to add the fog
2447 // color ontop through the fog mask texture
2449 // if this is an additive blended material, all the earlier passes
2450 // were darkened by fog already, and we should not add fog color
2451 // (because the background was not darkened, there is no fog color
2452 // that was lost behind it).
2453 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);
2460 void R_UpdateAllTextureInfo(entity_render_t *ent)
2464 for (i = 0;i < ent->model->num_textures;i++)
2465 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2468 float *rsurface_vertex3f;
2469 float *rsurface_svector3f;
2470 float *rsurface_tvector3f;
2471 float *rsurface_normal3f;
2472 float *rsurface_lightmapcolor4f;
2474 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
2476 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
2478 rsurface_vertex3f = varray_vertex3f;
2479 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
2480 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2482 rsurface_svector3f = varray_svector3f;
2483 rsurface_tvector3f = varray_tvector3f;
2484 rsurface_normal3f = varray_normal3f;
2485 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);
2489 rsurface_svector3f = NULL;
2490 rsurface_tvector3f = NULL;
2491 if (generatenormals)
2493 rsurface_normal3f = varray_normal3f;
2494 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);
2497 rsurface_normal3f = NULL;
2502 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
2503 rsurface_svector3f = surface->groupmesh->data_svector3f;
2504 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
2505 rsurface_normal3f = surface->groupmesh->data_normal3f;
2507 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2510 float center[3], forward[3], right[3], up[3], v[4][3];
2511 matrix4x4_t matrix1, imatrix1;
2512 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
2513 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
2514 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
2515 // a single autosprite surface can contain multiple sprites...
2516 for (j = 0;j < surface->num_vertices - 3;j += 4)
2518 VectorClear(center);
2519 for (i = 0;i < 4;i++)
2520 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2521 VectorScale(center, 0.25f, center);
2522 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2523 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);
2524 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2525 for (i = 0;i < 4;i++)
2526 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2527 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2529 forward[0] = modelorg[0] - center[0];
2530 forward[1] = modelorg[1] - center[1];
2532 VectorNormalize(forward);
2533 right[0] = forward[1];
2534 right[1] = -forward[0];
2536 VectorSet(up, 0, 0, 1);
2538 for (i = 0;i < 4;i++)
2539 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
2541 rsurface_vertex3f = varray_vertex3f;
2542 rsurface_svector3f = varray_svector3f;
2543 rsurface_tvector3f = varray_tvector3f;
2544 rsurface_normal3f = varray_normal3f;
2545 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);
2547 R_Mesh_VertexPointer(rsurface_vertex3f);
2550 static void RSurf_Draw(const msurface_t *surface)
2552 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2553 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2554 GL_LockArrays(0, 0);
2557 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)
2562 RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode >= 2, false);
2566 vec4_t ambientcolor;
2567 vec3_t diffusecolor;
2569 VectorCopy(ent->modellight_lightdir, lightdir);
2570 ambientcolor[0] = ent->modellight_ambient[0] * r * 0.5f;
2571 ambientcolor[1] = ent->modellight_ambient[1] * g * 0.5f;
2572 ambientcolor[2] = ent->modellight_ambient[2] * b * 0.5f;
2573 diffusecolor[0] = ent->modellight_diffuse[0] * r * 0.5f;
2574 diffusecolor[1] = ent->modellight_diffuse[1] * g * 0.5f;
2575 diffusecolor[2] = ent->modellight_diffuse[2] * b * 0.5f;
2576 if (VectorLength2(diffusecolor) > 0)
2578 int numverts = surface->num_vertices;
2579 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2580 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2581 c = varray_color4f + 4 * surface->num_firstvertex;
2582 // q3-style directional shading
2583 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2585 if ((f = DotProduct(c2, lightdir)) > 0)
2587 VectorMA(ambientcolor, f, diffusecolor, c);
2591 VectorCopy4(ambientcolor, c);
2598 rsurface_lightmapcolor4f = varray_color4f;
2602 r = ambientcolor[0];
2603 g = ambientcolor[1];
2604 b = ambientcolor[2];
2605 rsurface_lightmapcolor4f = NULL;
2608 else if (lightmode >= 1)
2610 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2612 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2614 if (surface->lightmapinfo->samples)
2616 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
2617 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2618 VectorScale(lm, scale, c);
2619 if (surface->lightmapinfo->styles[1] != 255)
2621 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2623 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2624 VectorMA(c, scale, lm, c);
2625 if (surface->lightmapinfo->styles[2] != 255)
2628 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2629 VectorMA(c, scale, lm, c);
2630 if (surface->lightmapinfo->styles[3] != 255)
2633 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2634 VectorMA(c, scale, lm, c);
2642 rsurface_lightmapcolor4f = varray_color4f;
2645 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
2648 rsurface_lightmapcolor4f = NULL;
2651 if (rsurface_lightmapcolor4f)
2653 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)
2655 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2664 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)
2666 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2673 rsurface_lightmapcolor4f = varray_color4f;
2675 if (applycolor && rsurface_lightmapcolor4f)
2677 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)
2684 rsurface_lightmapcolor4f = varray_color4f;
2686 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2687 GL_Color(r, g, b, a);
2688 RSurf_Draw(surface);
2691 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2693 int texturesurfaceindex;
2695 const msurface_t *surface;
2696 qboolean applycolor;
2699 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2701 r_shadow_rtlight = NULL;
2702 renderstats.entities_surfaces += texturenumsurfaces;
2703 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2704 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2705 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2706 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2707 qglDisable(GL_CULL_FACE);
2708 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2710 // transparent sky would be ridiculous
2711 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2716 skyrendernow = false;
2717 if (skyrendermasked)
2720 // restore entity matrix and GL_Color
2721 R_Mesh_Matrix(&ent->matrix);
2725 // LordHavoc: HalfLife maps have freaky skypolys...
2726 //if (!ent->model->brush.ishlbsp)
2728 if (skyrendermasked)
2730 // depth-only (masking)
2731 GL_ColorMask(0,0,0,0);
2732 // just to make sure that braindead drivers don't draw anything
2733 // despite that colormask...
2734 GL_BlendFunc(GL_ZERO, GL_ONE);
2739 GL_BlendFunc(GL_ONE, GL_ZERO);
2741 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2742 memset(&m, 0, sizeof(m));
2744 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2746 surface = texturesurfacelist[texturesurfaceindex];
2747 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2748 RSurf_Draw(surface);
2750 if (skyrendermasked)
2751 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2755 else if (r_glsl.integer && gl_support_fragment_shader)
2757 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2759 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2760 GL_DepthMask(false);
2762 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2764 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2765 GL_DepthMask(false);
2769 GL_BlendFunc(GL_ONE, GL_ZERO);
2773 memset(&m, 0, sizeof(m));
2775 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2776 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2777 if (!r_glsl_permutation)
2781 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2783 surface = texturesurfacelist[texturesurfaceindex];
2784 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2785 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2786 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2787 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2788 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2789 RSurf_Draw(surface);
2794 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2796 surface = texturesurfacelist[texturesurfaceindex];
2797 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2798 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2799 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2800 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2801 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2802 R_Mesh_TexCoordPointer(4, 2, surface->groupmesh->data_texcoordlightmap2f);
2803 if (surface->lightmaptexture)
2805 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2806 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2807 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2808 //R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2809 R_Mesh_ColorPointer(NULL);
2813 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2814 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2815 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2816 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2818 RSurf_Draw(surface);
2821 qglUseProgramObjectARB(0);
2823 else if (texture->currentnumlayers)
2826 texturelayer_t *layer;
2827 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2830 int layertexrgbscale;
2831 GL_DepthMask(layer->depthmask);
2832 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2833 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2835 layertexrgbscale = 4;
2836 VectorScale(layer->color, 0.25f, layercolor);
2838 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2840 layertexrgbscale = 2;
2841 VectorScale(layer->color, 0.5f, layercolor);
2845 layertexrgbscale = 1;
2846 VectorScale(layer->color, 1.0f, layercolor);
2848 layercolor[3] = layer->color[3];
2849 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2850 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2851 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2852 switch (layer->type)
2854 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2855 memset(&m, 0, sizeof(m));
2856 m.tex[1] = R_GetTexture(layer->texture);
2857 m.texmatrix[1] = layer->texmatrix;
2858 m.texrgbscale[1] = layertexrgbscale;
2859 m.pointer_color = varray_color4f;
2863 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2865 surface = texturesurfacelist[texturesurfaceindex];
2866 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2867 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2868 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2869 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2874 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2876 surface = texturesurfacelist[texturesurfaceindex];
2877 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2878 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2879 if (surface->lightmaptexture)
2881 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2882 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2886 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2887 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2892 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2893 memset(&m, 0, sizeof(m));
2894 m.tex[0] = R_GetTexture(layer->texture);
2895 m.texmatrix[0] = layer->texmatrix;
2896 m.pointer_color = varray_color4f;
2897 m.texrgbscale[0] = layertexrgbscale;
2901 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2903 surface = texturesurfacelist[texturesurfaceindex];
2904 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2905 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2906 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2911 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2913 surface = texturesurfacelist[texturesurfaceindex];
2914 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2915 if (surface->lightmaptexture)
2917 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2918 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
2922 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2923 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2927 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2928 memset(&m, 0, sizeof(m));
2929 m.tex[0] = R_GetTexture(layer->texture);
2930 m.texmatrix[0] = layer->texmatrix;
2931 m.pointer_color = varray_color4f;
2932 m.texrgbscale[0] = layertexrgbscale;
2934 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2936 surface = texturesurfacelist[texturesurfaceindex];
2937 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2938 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2941 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2942 memset(&m, 0, sizeof(m));
2943 m.tex[0] = R_GetTexture(layer->texture);
2944 m.texmatrix[0] = layer->texmatrix;
2945 m.texrgbscale[0] = layertexrgbscale;
2946 m.pointer_color = varray_color4f;
2950 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2952 surface = texturesurfacelist[texturesurfaceindex];
2953 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2954 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
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], 1, applycolor, applyfog);
2967 case TEXTURELAYERTYPE_TEXTURE:
2968 memset(&m, 0, sizeof(m));
2969 m.tex[0] = R_GetTexture(layer->texture);
2970 m.texmatrix[0] = layer->texmatrix;
2971 m.pointer_color = varray_color4f;
2972 m.texrgbscale[0] = layertexrgbscale;
2974 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2976 surface = texturesurfacelist[texturesurfaceindex];
2977 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2978 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2981 case TEXTURELAYERTYPE_FOG:
2982 memset(&m, 0, sizeof(m));
2985 m.tex[0] = R_GetTexture(layer->texture);
2986 m.texmatrix[0] = layer->texmatrix;
2989 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2993 surface = texturesurfacelist[texturesurfaceindex];
2994 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2996 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2997 R_Mesh_ColorPointer(varray_color4f);
2998 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)
3000 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
3001 c[0] = layercolor[0];
3002 c[1] = layercolor[1];
3003 c[2] = layercolor[2];
3004 c[3] = f * layercolor[3];
3006 RSurf_Draw(surface);
3010 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3012 // if trying to do overbright on first pass of an opaque surface
3013 // when combine is not supported, brighten as a post process
3014 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3017 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3018 GL_Color(1, 1, 1, 1);
3019 memset(&m, 0, sizeof(m));
3021 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3023 surface = texturesurfacelist[texturesurfaceindex];
3024 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
3025 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3026 RSurf_Draw(surface);
3030 if (r_shownormals.integer && !r_showtrispass)
3034 GL_DepthTest(!r_showdisabledepthtest.integer);
3035 GL_DepthMask(texture->currentlayers->depthmask);
3036 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
3037 memset(&m, 0, sizeof(m));
3039 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3041 surface = texturesurfacelist[texturesurfaceindex];
3042 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
3043 GL_Color(1, 0, 0, 1);
3045 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3047 VectorCopy(rsurface_vertex3f + k * 3, v);
3048 qglVertex3f(v[0], v[1], v[2]);
3049 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
3050 qglVertex3f(v[0], v[1], v[2]);
3052 GL_Color(0, 0, 1, 1);
3053 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3055 VectorCopy(rsurface_vertex3f + k * 3, v);
3056 qglVertex3f(v[0], v[1], v[2]);
3057 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
3058 qglVertex3f(v[0], v[1], v[2]);
3060 GL_Color(0, 1, 0, 1);
3061 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3063 VectorCopy(rsurface_vertex3f + k * 3, v);
3064 qglVertex3f(v[0], v[1], v[2]);
3065 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
3066 qglVertex3f(v[0], v[1], v[2]);
3072 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3073 qglEnable(GL_CULL_FACE);
3076 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3078 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3082 texture = surface->texture;
3083 if (texture->basematerialflags & MATERIALFLAG_SKY)
3084 return; // transparent sky is too difficult
3085 R_UpdateTextureInfo(ent, texture);
3087 R_Mesh_Matrix(&ent->matrix);
3088 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3089 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3092 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
3094 int texturesurfaceindex;
3095 const msurface_t *surface;
3096 vec3_t tempcenter, center;
3097 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3099 // drawing sky transparently would be too difficult
3100 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3102 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3104 surface = texturesurfacelist[texturesurfaceindex];
3105 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3106 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3107 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3108 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3109 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3114 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3117 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3118 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3120 int i, j, f, flagsmask;
3121 int counttriangles = 0;
3122 msurface_t *surface, **surfacechain;
3123 texture_t *t, *texture;
3124 model_t *model = ent->model;
3126 const int maxsurfacelist = 1024;
3127 int numsurfacelist = 0;
3128 const msurface_t *surfacelist[1024];
3131 R_Mesh_Matrix(&ent->matrix);
3132 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3134 // update light styles
3135 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3137 for (i = 0;i < model->brushq1.light_styles;i++)
3139 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3141 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3142 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3143 for (;(surface = *surfacechain);surfacechain++)
3144 surface->cached_dlight = true;
3149 R_UpdateAllTextureInfo(ent);
3150 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3155 if (ent == r_refdef.worldentity)
3157 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3159 if (!r_worldsurfacevisible[j])
3161 if (t != surface->texture)
3165 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3168 t = surface->texture;
3169 texture = t->currentframe;
3170 f = texture->currentmaterialflags & flagsmask;
3172 if (f && surface->num_triangles)
3174 // if lightmap parameters changed, rebuild lightmap texture
3175 if (surface->cached_dlight)
3176 R_BuildLightMap(ent, surface);
3177 // add face to draw list
3178 surfacelist[numsurfacelist++] = surface;
3179 counttriangles += surface->num_triangles;
3180 if (numsurfacelist >= maxsurfacelist)
3182 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3190 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3192 if (t != surface->texture)
3196 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3199 t = surface->texture;
3200 texture = t->currentframe;
3201 f = texture->currentmaterialflags & flagsmask;
3203 if (f && surface->num_triangles)
3205 // if lightmap parameters changed, rebuild lightmap texture
3206 if (surface->cached_dlight)
3207 R_BuildLightMap(ent, surface);
3208 // add face to draw list
3209 surfacelist[numsurfacelist++] = surface;
3210 counttriangles += surface->num_triangles;
3211 if (numsurfacelist >= maxsurfacelist)
3213 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3220 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3221 if (!r_showtrispass)
3222 renderstats.entities_triangles += counttriangles;
3223 if (gl_support_fragment_shader)
3224 qglUseProgramObjectARB(0);