2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 mempool_t *r_main_mempool;
27 rtexturepool_t *r_main_texturepool;
29 // used for dlight push checking and other things
34 renderstats_t renderstats;
36 // true during envmap command capture
39 // maximum visible distance (recalculated from world box each frame)
41 // brightness of world lightmaps and related lighting
42 // (often reduced when world rtlights are enabled)
43 float r_lightmapintensity;
44 // whether to draw world lights realtime, dlights realtime, and their shadows
46 qboolean r_rtworldshadows;
48 qboolean r_rtdlightshadows;
51 // forces all rendering to draw triangle outlines
66 matrix4x4_t r_view_matrix;
73 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_showtris_polygonoffset = {0, "r_showtris_polygonoffset", "-10", "nudges triangle outlines in hardware depth units, used to make outlines appear infront of walls"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing\n"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
85 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
86 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
87 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
88 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
89 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
91 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
92 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
93 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
94 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
95 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
96 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
97 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
99 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
101 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
102 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "enables offset mapping effect (also known as parallax mapping or sometimes as virtual displacement mapping, not as good as relief mapping or silohuette mapping but much faster), can cause strange artifacts on many textures, requires bumpmaps for depth information (normalmaps can have depth information as alpha channel, but most do not)"};
103 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "-0.04", "how deep the offset mapping effect is, and whether it is inward or outward"};
104 cvar_t r_glsl_offsetmapping_bias = {0, "r_glsl_offsetmapping_bias", "0.04", "pushes the effect closer/further"};
105 cvar_t r_glsl_usehalffloat = {0, "r_glsl_usehalffloat", "0", "use half and hvec variables in GLSL shader for a speed gain (NVIDIA only)"};
106 cvar_t r_glsl_surfacenormalize = {0, "r_glsl_surfacenormalize", "1", "normalize bumpmap texels in GLSL shader, produces a more rounded look on small bumps and dents"};
108 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
109 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
110 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
112 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
113 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "1.5", "how bright the glow is"};
114 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
115 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
116 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "2", "how much to darken the image before blurring to make the bloom effect"};
118 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
120 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
122 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
124 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"}; // used for testing renderer code changes, otherwise does nothing
126 rtexture_t *r_bloom_texture_screen;
127 rtexture_t *r_bloom_texture_bloom;
128 rtexture_t *r_texture_blanknormalmap;
129 rtexture_t *r_texture_white;
130 rtexture_t *r_texture_black;
131 rtexture_t *r_texture_notexture;
132 rtexture_t *r_texture_whitecube;
133 rtexture_t *r_texture_normalizationcube;
134 rtexture_t *r_texture_fogattenuation;
135 rtexture_t *r_texture_fogintensity;
137 // information about each possible shader permutation
138 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
139 // currently selected permutation
140 r_glsl_permutation_t *r_glsl_permutation;
142 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
145 for (i = 0;i < verts;i++)
156 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
159 for (i = 0;i < verts;i++)
174 vec_t fogtabledistmultiplier;
175 float fogtable[FOGTABLEWIDTH];
176 float fog_density, fog_red, fog_green, fog_blue;
178 qboolean oldgl_fogenable;
179 void R_UpdateFog(void)
181 if (gamemode == GAME_NEHAHRA)
183 if (gl_fogenable.integer)
185 oldgl_fogenable = true;
186 fog_density = gl_fogdensity.value;
187 fog_red = gl_fogred.value;
188 fog_green = gl_foggreen.value;
189 fog_blue = gl_fogblue.value;
191 else if (oldgl_fogenable)
193 oldgl_fogenable = false;
202 fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f);
203 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
204 fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f);
209 fogdensity = -4000.0f / (fog_density * fog_density);
210 // this is the point where the fog reaches 0.9986 alpha, which we
211 // consider a good enough cutoff point for the texture
212 // (0.9986 * 256 == 255.6)
213 fogrange = 400 / fog_density;
214 fograngerecip = 1.0f / fogrange;
215 fogtabledistmultiplier = FOGTABLEWIDTH * fograngerecip;
216 // fog color was already set
222 // FIXME: move this to client?
225 if (gamemode == GAME_NEHAHRA)
227 Cvar_Set("gl_fogenable", "0");
228 Cvar_Set("gl_fogdensity", "0.2");
229 Cvar_Set("gl_fogred", "0.3");
230 Cvar_Set("gl_foggreen", "0.3");
231 Cvar_Set("gl_fogblue", "0.3");
233 fog_density = fog_red = fog_green = fog_blue = 0.0f;
236 // FIXME: move this to client?
237 void FOG_registercvars(void)
242 if (gamemode == GAME_NEHAHRA)
244 Cvar_RegisterVariable (&gl_fogenable);
245 Cvar_RegisterVariable (&gl_fogdensity);
246 Cvar_RegisterVariable (&gl_fogred);
247 Cvar_RegisterVariable (&gl_foggreen);
248 Cvar_RegisterVariable (&gl_fogblue);
249 Cvar_RegisterVariable (&gl_fogstart);
250 Cvar_RegisterVariable (&gl_fogend);
253 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
254 for (x = 0;x < FOGTABLEWIDTH;x++)
256 alpha = exp(r / ((double)x*(double)x));
257 if (x == FOGTABLEWIDTH - 1)
259 fogtable[x] = bound(0, alpha, 1);
263 static void R_BuildBlankTextures(void)
265 unsigned char data[4];
266 data[0] = 128; // normal X
267 data[1] = 128; // normal Y
268 data[2] = 255; // normal Z
269 data[3] = 128; // height
270 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
275 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
280 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
283 static void R_BuildNoTexture(void)
286 unsigned char pix[16][16][4];
287 // this makes a light grey/dark grey checkerboard texture
288 for (y = 0;y < 16;y++)
290 for (x = 0;x < 16;x++)
292 if ((y < 8) ^ (x < 8))
308 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
311 static void R_BuildWhiteCube(void)
313 unsigned char data[6*1*1*4];
314 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
315 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
316 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
317 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
318 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
319 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
320 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
323 static void R_BuildNormalizationCube(void)
327 vec_t s, t, intensity;
329 unsigned char data[6][NORMSIZE][NORMSIZE][4];
330 for (side = 0;side < 6;side++)
332 for (y = 0;y < NORMSIZE;y++)
334 for (x = 0;x < NORMSIZE;x++)
336 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
337 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
372 intensity = 127.0f / sqrt(DotProduct(v, v));
373 data[side][y][x][0] = 128.0f + intensity * v[0];
374 data[side][y][x][1] = 128.0f + intensity * v[1];
375 data[side][y][x][2] = 128.0f + intensity * v[2];
376 data[side][y][x][3] = 255;
380 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
383 static void R_BuildFogTexture(void)
388 unsigned char data1[FOGWIDTH][4];
389 unsigned char data2[FOGWIDTH][4];
390 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
391 for (x = 0;x < FOGWIDTH;x++)
393 alpha = exp(r / ((double)x*(double)x));
394 if (x == FOGWIDTH - 1)
396 b = (int)(256.0 * alpha);
397 b = bound(0, b, 255);
398 data1[x][0] = 255 - b;
399 data1[x][1] = 255 - b;
400 data1[x][2] = 255 - b;
407 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
408 r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
411 static const char *builtinshaderstring =
412 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
413 "// written by Forest 'LordHavoc' Hale\n"
415 "// common definitions between vertex shader and fragment shader:\n"
417 "// use half floats if available for math performance\n"
419 "#define myhalf half\n"
420 "#define myhvec2 hvec2\n"
421 "#define myhvec3 hvec3\n"
422 "#define myhvec4 hvec4\n"
424 "#define myhalf float\n"
425 "#define myhvec2 vec2\n"
426 "#define myhvec3 vec3\n"
427 "#define myhvec4 vec4\n"
430 "varying vec2 TexCoord;\n"
431 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
432 "varying vec2 TexCoordLightmap;\n"
435 "#ifdef MODE_LIGHTSOURCE\n"
436 "varying myhvec3 CubeVector;\n"
439 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
440 "varying vec3 LightVector;\n"
443 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
444 "varying vec3 EyeVector;\n"
450 "// vertex shader specific:\n"
451 "#ifdef VERTEX_SHADER\n"
453 "#ifdef MODE_LIGHTSOURCE\n"
454 "uniform vec3 LightPosition;\n"
457 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
458 "uniform vec3 EyePosition;\n"
461 "#ifdef MODE_LIGHTDIRECTION\n"
462 "uniform myhvec3 LightDir;\n"
465 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
469 " // copy the surface texcoord\n"
470 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
471 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
472 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
474 " gl_FrontColor = gl_Color;\n"
476 "#ifdef MODE_LIGHTSOURCE\n"
477 " // transform vertex position into light attenuation/cubemap space\n"
478 " // (-1 to +1 across the light box)\n"
479 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
481 " // transform unnormalized light direction into tangent space\n"
482 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
483 " // normalize it per pixel)\n"
484 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
485 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
486 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
487 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
490 "#ifdef MODE_LIGHTDIRECTION\n"
491 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
492 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
493 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
496 "#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)\n"
497 " // transform unnormalized eye direction into tangent space\n"
498 " vec3 eyeminusvertex = EyePosition - gl_Vertex.xyz;\n"
499 " EyeVector.x = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);\n"
500 " EyeVector.y = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);\n"
501 " EyeVector.z = dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n"
504 " // transform vertex to camera space, using ftransform to match non-VS\n"
506 " gl_Position = ftransform();\n"
514 "// fragment shader specific:\n"
515 "#ifdef FRAGMENT_SHADER\n"
517 "uniform myhvec3 LightColor;\n"
518 "#ifdef USEOFFSETMAPPING\n"
519 "uniform myhalf OffsetMapping_Scale;\n"
520 "uniform myhalf OffsetMapping_Bias;\n"
523 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTIONMAP) || defined(MODE_LIGHTDIRECTION) || defined(USEOFFSETMAPPING)\n"
524 "uniform sampler2D Texture_Normal;\n"
527 "#ifdef MODE_LIGHTDIRECTION\n"
528 "uniform myhvec3 AmbientColor;\n"
529 "uniform myhvec3 DiffuseColor;\n"
530 "uniform myhvec3 SpecularColor;\n"
533 "uniform sampler2D Texture_Color;\n"
535 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
536 "uniform sampler2D Texture_Lightmap;\n"
538 "#ifdef MODE_LIGHTDIRECTIONMAP\n"
539 "uniform sampler2D Texture_Deluxemap;\n"
543 "uniform sampler2D Texture_Glow;\n"
546 "#ifdef USECOLORMAPPING\n"
547 "uniform sampler2D Texture_Pants;\n"
548 "uniform sampler2D Texture_Shirt;\n"
549 "uniform myhvec3 Color_Pants;\n"
550 "uniform myhvec3 Color_Shirt;\n"
553 "uniform myhalf AmbientScale;\n"
554 "uniform myhalf DiffuseScale;\n"
555 "#ifdef USESPECULAR\n"
556 "uniform myhalf SpecularScale;\n"
557 "uniform myhalf SpecularPower;\n"
558 "uniform sampler2D Texture_Gloss;\n"
561 "#ifdef USECUBEFILTER\n"
562 "uniform samplerCube Texture_Cube;\n"
566 "uniform myhvec3 FogColor;\n"
567 "uniform myhalf FogRangeRecip;\n"
568 "uniform sampler2D Texture_FogMask;\n"
571 "#ifdef USEEASTEREGG\n"
574 " gl_FragColor = myhvec4(0, 0, 0, 1);;\n"
577 " vec2 p = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
578 " vec2 c = vec2(CubeVector.x * 16.0, CubeVector.y * 16.0);\n"
579 " for (i = 0;i < 1000 && dot(p,p) < 4.0;i = i + 1)\n"
581 " o = p.x * p.x - p.y * p.y;\n"
582 " p.y = 2.0 * p.x * p.y;\n"
586 " o = float(i) * 0.314;\n"
588 " gl_FragColor = vec4(cos(o), sin(o), sin(o * 0.2), 1);\n"
590 "#else // USEEASTEREGG\n"
596 " // apply offsetmapping\n"
597 "#ifdef USEOFFSETMAPPING\n"
598 " // this is 3 sample because of ATI Radeon 9500-9800/X300 limits\n"
599 " myhvec2 OffsetVector = normalize(EyeVector).xy * vec2(-0.333, 0.333);\n"
600 " myhvec2 TexCoordOffset = TexCoord + OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).w);\n"
601 " TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoordOffset).w);\n"
602 " TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(Texture_Normal, TexCoordOffset).w);\n"
603 "#define TexCoord TexCoordOffset\n"
606 " // combine the diffuse textures (base, pants, shirt)\n"
607 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
608 "#ifdef USECOLORMAPPING\n"
609 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
615 "#ifdef MODE_LIGHTSOURCE\n"
618 " // get the surface normal and light normal\n"
619 "#ifdef SURFACENORMALIZE\n"
620 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
622 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
624 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
626 " // calculate directional shading\n"
627 " color.rgb *= (AmbientScale + DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
628 "#ifdef USESPECULAR\n"
629 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
630 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
633 "#ifdef USECUBEFILTER\n"
634 " // apply light cubemap filter\n"
635 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
638 " // apply light color\n"
639 " color.rgb = color.rgb * LightColor;\n"
641 " // apply attenuation\n"
643 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
644 " // center and sharp falloff at the edge, this is about the most efficient\n"
645 " // we can get away with as far as providing illumination.\n"
647 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
648 " // provide significant illumination, large = slow = pain.\n"
649 " color.rgb *= max(1.0 - dot(CubeVector, CubeVector), 0.0);\n"
654 "#elif defined(MODE_LIGHTDIRECTION)\n"
655 " // directional model lighting\n"
657 " // get the surface normal and light normal\n"
658 "#ifdef SURFACENORMALIZE\n"
659 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
661 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
663 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
666 " // calculate directional shading\n"
667 " color.rgb *= AmbientColor + DiffuseColor * max(dot(surfacenormal, diffusenormal), 0.0);\n"
668 "#ifdef USESPECULAR\n"
669 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
670 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
676 "#elif defined(MODE_LIGHTDIRECTIONMAP)\n"
677 " // deluxemap lightmapping\n"
679 " // get the surface normal and light normal\n"
680 "#ifdef SURFACENORMALIZE\n"
681 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - 0.5);\n"
682 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - 0.5);\n"
684 " myhvec3 surfacenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Normal, TexCoord));\n"
685 " myhvec3 diffusenormal = -1.0 + 2.0 * myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap));\n"
688 " // calculate directional shading\n"
689 " myhvec3 tempcolor = color.rgb * (DiffuseScale * max(dot(surfacenormal, diffusenormal), 0.0));\n"
690 "#ifdef USESPECULAR\n"
691 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
692 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(max(dot(surfacenormal, specularnormal), 0.0), SpecularPower);\n"
695 " // apply lightmap color\n"
696 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * myhvec3(AmbientScale);\n"
701 "#else // MODE none (lightmap)\n"
702 " // apply lightmap color\n"
703 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
707 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord));\n"
712 " myhalf fog = texture2D(Texture_FogMask, myhvec2(length(EyeVector)*FogRangeRecip, 0.0)).x;\n"
713 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
716 " gl_FragColor = color * gl_Color;\n"
718 "#endif // !USEEASTEREGG\n"
723 // the loaded GLSL shader file for compiling shader permutations as needed
724 static char *shaderstring = NULL;
726 void R_GLSL_CompilePermutation(int permutation)
728 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
729 int vertstrings_count;
730 int fragstrings_count;
731 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
732 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
733 char permutationname[256];
737 vertstrings_list[0] = "#define VERTEX_SHADER\n";
738 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
739 vertstrings_count = 1;
740 fragstrings_count = 1;
741 permutationname[0] = 0;
742 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
744 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTSOURCE\n";
745 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTSOURCE\n";
746 strlcat(permutationname, " lightsource", sizeof(permutationname));
748 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP)
750 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP\n";
751 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTIONMAP\n";
752 strlcat(permutationname, " lightdirectionmap", sizeof(permutationname));
754 if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
756 vertstrings_list[vertstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
757 fragstrings_list[fragstrings_count++] = "#define MODE_LIGHTDIRECTION\n";
758 strlcat(permutationname, " lightdirection", sizeof(permutationname));
760 if (permutation & SHADERPERMUTATION_GLOW)
762 vertstrings_list[vertstrings_count++] = "#define USEGLOW\n";
763 fragstrings_list[fragstrings_count++] = "#define USEGLOW\n";
764 strlcat(permutationname, " glow", sizeof(permutationname));
766 if (permutation & SHADERPERMUTATION_COLORMAPPING)
768 vertstrings_list[vertstrings_count++] = "#define USECOLORMAPPING\n";
769 fragstrings_list[fragstrings_count++] = "#define USECOLORMAPPING\n";
770 strlcat(permutationname, " colormapping", sizeof(permutationname));
772 if (permutation & SHADERPERMUTATION_SPECULAR)
774 vertstrings_list[vertstrings_count++] = "#define USESPECULAR\n";
775 fragstrings_list[fragstrings_count++] = "#define USESPECULAR\n";
776 strlcat(permutationname, " specular", sizeof(permutationname));
778 if (permutation & SHADERPERMUTATION_FOG)
780 vertstrings_list[vertstrings_count++] = "#define USEFOG\n";
781 fragstrings_list[fragstrings_count++] = "#define USEFOG\n";
782 strlcat(permutationname, " fog", sizeof(permutationname));
784 if (permutation & SHADERPERMUTATION_CUBEFILTER)
786 vertstrings_list[vertstrings_count++] = "#define USECUBEFILTER\n";
787 fragstrings_list[fragstrings_count++] = "#define USECUBEFILTER\n";
788 strlcat(permutationname, " cubefilter", sizeof(permutationname));
790 if (permutation & SHADERPERMUTATION_OFFSETMAPPING)
792 vertstrings_list[vertstrings_count++] = "#define USEOFFSETMAPPING\n";
793 fragstrings_list[fragstrings_count++] = "#define USEOFFSETMAPPING\n";
794 strlcat(permutationname, " offsetmapping", sizeof(permutationname));
796 if (permutation & SHADERPERMUTATION_SURFACENORMALIZE)
798 vertstrings_list[vertstrings_count++] = "#define SURFACENORMALIZE\n";
799 fragstrings_list[fragstrings_count++] = "#define SURFACENORMALIZE\n";
800 strlcat(permutationname, " surfacenormalize", sizeof(permutationname));
802 if (permutation & SHADERPERMUTATION_GEFORCEFX)
804 vertstrings_list[vertstrings_count++] = "#define GEFORCEFX\n";
805 fragstrings_list[fragstrings_count++] = "#define GEFORCEFX\n";
806 strlcat(permutationname, " halffloat", sizeof(permutationname));
810 vertstrings_list[vertstrings_count++] = shaderstring;
811 fragstrings_list[fragstrings_count++] = shaderstring;
815 vertstrings_list[vertstrings_count++] = builtinshaderstring;
816 fragstrings_list[fragstrings_count++] = builtinshaderstring;
818 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
822 qglUseProgramObjectARB(p->program);
823 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
824 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
825 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
826 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
827 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
828 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
829 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
830 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
831 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
832 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
833 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
834 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
835 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
836 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
837 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
838 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
839 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
840 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
841 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
842 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
843 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
844 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
845 p->loc_OffsetMapping_Bias = qglGetUniformLocationARB(p->program, "OffsetMapping_Bias");
846 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
847 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
848 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
849 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
850 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
851 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
852 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
853 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
854 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
855 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
856 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
857 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
858 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
859 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
860 qglUseProgramObjectARB(0);
864 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
867 void R_SetupSurfaceShader(const entity_render_t *ent, const texture_t *texture, const vec3_t modelorg, const vec3_t lightcolorbase, qboolean modellighting)
869 // select a permutation of the lighting shader appropriate to this
870 // combination of texture, entity, light source, and fogging, only use the
871 // minimum features necessary to avoid wasting rendering time in the
872 // fragment shader on features that are not being used
874 float specularscale = texture->specularscale;
875 r_glsl_permutation = NULL;
876 if (r_shadow_rtlight)
878 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
879 specularscale *= r_shadow_rtlight->specularscale;
880 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
881 permutation |= SHADERPERMUTATION_CUBEFILTER;
883 else if (modellighting)
885 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
886 if (texture->skin.glow)
887 permutation |= SHADERPERMUTATION_GLOW;
889 else if (r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
891 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP;
892 if (texture->skin.glow)
893 permutation |= SHADERPERMUTATION_GLOW;
897 if (texture->skin.glow)
898 permutation |= SHADERPERMUTATION_GLOW;
900 if (specularscale > 0)
901 permutation |= SHADERPERMUTATION_SPECULAR;
903 permutation |= SHADERPERMUTATION_FOG;
904 if (texture->colormapping)
905 permutation |= SHADERPERMUTATION_COLORMAPPING;
906 if (r_glsl_offsetmapping.integer)
907 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
908 if (r_glsl_surfacenormalize.integer)
909 permutation |= SHADERPERMUTATION_SURFACENORMALIZE;
910 if (r_glsl_usehalffloat.integer)
911 permutation |= SHADERPERMUTATION_GEFORCEFX;
912 if (!r_glsl_permutations[permutation].program)
914 if (!r_glsl_permutations[permutation].compiled)
915 R_GLSL_CompilePermutation(permutation);
916 if (!r_glsl_permutations[permutation].program)
918 // remove features until we find a valid permutation
920 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
922 // reduce i more quickly whenever it would not remove any bits
926 if (!r_glsl_permutations[permutation].compiled)
927 R_GLSL_CompilePermutation(permutation);
928 if (r_glsl_permutations[permutation].program)
931 return; // utterly failed
935 r_glsl_permutation = r_glsl_permutations + permutation;
937 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
938 R_Mesh_TexMatrix(0, &texture->currenttexmatrix);
939 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
941 R_Mesh_TexMatrix(3, &r_shadow_entitytolight);
942 if (r_glsl_permutation->loc_Texture_Cube >= 0) R_Mesh_TexBind(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
943 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]);
944 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
945 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
946 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
947 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
949 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
951 if (texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
953 if (r_glsl_permutation->loc_AmbientColor >= 0)
954 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, 1, 1, 1);
955 if (r_glsl_permutation->loc_DiffuseColor >= 0)
956 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, 0, 0, 0);
957 if (r_glsl_permutation->loc_SpecularColor >= 0)
958 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, 0, 0, 0);
959 if (r_glsl_permutation->loc_LightDir >= 0)
960 qglUniform3fARB(r_glsl_permutation->loc_LightDir, 0, 0, -1);
964 if (r_glsl_permutation->loc_AmbientColor >= 0)
965 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, ent->modellight_ambient[0], ent->modellight_ambient[1], ent->modellight_ambient[2]);
966 if (r_glsl_permutation->loc_DiffuseColor >= 0)
967 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, ent->modellight_diffuse[0], ent->modellight_diffuse[1], ent->modellight_diffuse[2]);
968 if (r_glsl_permutation->loc_SpecularColor >= 0)
969 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, ent->modellight_diffuse[0] * texture->specularscale, ent->modellight_diffuse[1] * texture->specularscale, ent->modellight_diffuse[2] * texture->specularscale);
970 if (r_glsl_permutation->loc_LightDir >= 0)
971 qglUniform3fARB(r_glsl_permutation->loc_LightDir, ent->modellight_lightdir[0], ent->modellight_lightdir[1], ent->modellight_lightdir[2]);
976 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
977 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_lightmapintensity * 2.0f);
978 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale * 2.0f);
980 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(texture->skin.nmap));
981 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(texture->basetexture));
982 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(texture->glosstexture));
983 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
984 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(texture->skin.pants));
985 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(texture->skin.shirt));
986 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(texture->skin.glow));
987 if (r_glsl_permutation->loc_FogColor >= 0)
989 // additive passes are only darkened by fog, not tinted
990 if (r_shadow_rtlight || (texture->currentmaterialflags & MATERIALFLAG_ADD))
991 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
993 qglUniform3fARB(r_glsl_permutation->loc_FogColor, fogcolor[0], fogcolor[1], fogcolor[2]);
995 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, modelorg[0], modelorg[1], modelorg[2]);
996 if (r_glsl_permutation->loc_Color_Pants >= 0)
998 if (texture->skin.pants)
999 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, ent->colormap_pantscolor[0], ent->colormap_pantscolor[1], ent->colormap_pantscolor[2]);
1001 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1003 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1005 if (texture->skin.shirt)
1006 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, ent->colormap_shirtcolor[0], ent->colormap_shirtcolor[1], ent->colormap_shirtcolor[2]);
1008 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1010 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, fograngerecip);
1011 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, texture->specularpower);
1012 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1013 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Bias, r_glsl_offsetmapping_bias.value);
1017 void gl_main_start(void)
1019 // use half float math where available (speed gain on NVIDIA GFFX and GF6)
1020 if (gl_support_half_float)
1021 Cvar_SetValue("r_glsl_usehalffloat", 1);
1022 r_main_texturepool = R_AllocTexturePool();
1023 r_bloom_texture_screen = NULL;
1024 r_bloom_texture_bloom = NULL;
1025 R_BuildBlankTextures();
1027 if (gl_texturecubemap)
1030 R_BuildNormalizationCube();
1032 R_BuildFogTexture();
1033 shaderstring = NULL;
1034 if (gl_support_fragment_shader)
1036 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
1038 Con_Printf("GLSL shader text loaded from disk\n");
1039 // if we couldn't load the shader file, fall back to builtin shader
1043 Con_Printf("GLSL shader text loaded from fallback\n");
1044 shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1045 strcpy(shaderstring, builtinshaderstring);
1049 Con_Printf("GLSL shader text loaded\n");
1050 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1053 void gl_main_shutdown(void)
1056 R_FreeTexturePool(&r_main_texturepool);
1057 r_bloom_texture_screen = NULL;
1058 r_bloom_texture_bloom = NULL;
1059 r_texture_blanknormalmap = NULL;
1060 r_texture_white = NULL;
1061 r_texture_black = NULL;
1062 r_texture_whitecube = NULL;
1063 r_texture_normalizationcube = NULL;
1065 Mem_Free(shaderstring);
1066 shaderstring = NULL;
1067 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1068 if (r_glsl_permutations[i].program)
1069 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
1070 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1073 extern void CL_ParseEntityLump(char *entitystring);
1074 void gl_main_newmap(void)
1076 // FIXME: move this code to client
1078 char *entities, entname[MAX_QPATH];
1082 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1083 l = (int)strlen(entname) - 4;
1084 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1086 strcpy(entname + l, ".ent");
1087 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1089 CL_ParseEntityLump(entities);
1094 if (cl.worldmodel->brush.entities)
1095 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1099 void GL_Main_Init(void)
1101 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1103 FOG_registercvars(); // FIXME: move this fog stuff to client?
1104 Cvar_RegisterVariable(&r_nearclip);
1105 Cvar_RegisterVariable(&r_showtris);
1106 Cvar_RegisterVariable(&r_showtris_polygonoffset);
1107 Cvar_RegisterVariable(&r_shownormals);
1108 Cvar_RegisterVariable(&r_showlighting);
1109 Cvar_RegisterVariable(&r_showshadowvolumes);
1110 Cvar_RegisterVariable(&r_showcollisionbrushes);
1111 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1112 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1113 Cvar_RegisterVariable(&r_showdisabledepthtest);
1114 Cvar_RegisterVariable(&r_drawentities);
1115 Cvar_RegisterVariable(&r_drawviewmodel);
1116 Cvar_RegisterVariable(&r_speeds);
1117 Cvar_RegisterVariable(&r_fullbrights);
1118 Cvar_RegisterVariable(&r_wateralpha);
1119 Cvar_RegisterVariable(&r_dynamic);
1120 Cvar_RegisterVariable(&r_fullbright);
1121 Cvar_RegisterVariable(&r_textureunits);
1122 Cvar_RegisterVariable(&r_glsl);
1123 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1124 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1125 Cvar_RegisterVariable(&r_glsl_offsetmapping_bias);
1126 Cvar_RegisterVariable(&r_glsl_usehalffloat);
1127 Cvar_RegisterVariable(&r_glsl_surfacenormalize);
1128 Cvar_RegisterVariable(&r_lerpsprites);
1129 Cvar_RegisterVariable(&r_lerpmodels);
1130 Cvar_RegisterVariable(&r_waterscroll);
1131 Cvar_RegisterVariable(&r_bloom);
1132 Cvar_RegisterVariable(&r_bloom_intensity);
1133 Cvar_RegisterVariable(&r_bloom_blur);
1134 Cvar_RegisterVariable(&r_bloom_resolution);
1135 Cvar_RegisterVariable(&r_bloom_power);
1136 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1137 Cvar_RegisterVariable(&developer_texturelogging);
1138 Cvar_RegisterVariable(&gl_lightmaps);
1139 Cvar_RegisterVariable(&r_test);
1140 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1141 Cvar_SetValue("r_fullbrights", 0);
1142 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1145 static vec3_t r_farclip_origin;
1146 static vec3_t r_farclip_direction;
1147 static vec_t r_farclip_directiondist;
1148 static vec_t r_farclip_meshfarclip;
1149 static int r_farclip_directionbit0;
1150 static int r_farclip_directionbit1;
1151 static int r_farclip_directionbit2;
1153 // enlarge farclip to accomodate box
1154 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
1157 d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
1158 + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
1159 + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
1160 if (r_farclip_meshfarclip < d)
1161 r_farclip_meshfarclip = d;
1164 // return farclip value
1165 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
1169 VectorCopy(origin, r_farclip_origin);
1170 VectorCopy(direction, r_farclip_direction);
1171 r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
1172 r_farclip_directionbit0 = r_farclip_direction[0] < 0;
1173 r_farclip_directionbit1 = r_farclip_direction[1] < 0;
1174 r_farclip_directionbit2 = r_farclip_direction[2] < 0;
1175 r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
1177 if (r_refdef.worldmodel)
1178 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1179 for (i = 0;i < r_refdef.numentities;i++)
1180 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
1182 return r_farclip_meshfarclip - r_farclip_directiondist;
1185 extern void R_Textures_Init(void);
1186 extern void GL_Draw_Init(void);
1187 extern void GL_Main_Init(void);
1188 extern void R_Shadow_Init(void);
1189 extern void R_Sky_Init(void);
1190 extern void GL_Surf_Init(void);
1191 extern void R_Crosshairs_Init(void);
1192 extern void R_Light_Init(void);
1193 extern void R_Particles_Init(void);
1194 extern void R_Explosion_Init(void);
1195 extern void gl_backend_init(void);
1196 extern void Sbar_Init(void);
1197 extern void R_LightningBeams_Init(void);
1198 extern void Mod_RenderInit(void);
1200 void Render_Init(void)
1210 R_Crosshairs_Init();
1215 R_LightningBeams_Init();
1224 extern char *ENGINE_EXTENSIONS;
1227 VID_CheckExtensions();
1229 // LordHavoc: report supported extensions
1230 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1232 // clear to black (loading plaque will be seen over this)
1233 qglClearColor(0,0,0,1);
1234 qglClear(GL_COLOR_BUFFER_BIT);
1237 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1241 for (i = 0;i < 4;i++)
1248 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1252 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1256 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1260 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1264 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1268 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1272 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1276 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1284 //==================================================================================
1286 static void R_UpdateEntityLighting(entity_render_t *ent)
1288 vec3_t tempdiffusenormal;
1289 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));
1290 VectorClear(ent->modellight_diffuse);
1291 VectorClear(ent->modellight_lightdir);
1292 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1293 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, ent->origin, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1295 VectorSet(ent->modellight_ambient, 1, 1, 1);
1296 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1297 VectorNormalize(ent->modellight_lightdir);
1298 ent->modellight_ambient[0] *= ent->colormod[0] * r_lightmapintensity;
1299 ent->modellight_ambient[1] *= ent->colormod[1] * r_lightmapintensity;
1300 ent->modellight_ambient[2] *= ent->colormod[2] * r_lightmapintensity;
1301 ent->modellight_diffuse[0] *= ent->colormod[0] * r_lightmapintensity;
1302 ent->modellight_diffuse[1] *= ent->colormod[1] * r_lightmapintensity;
1303 ent->modellight_diffuse[2] *= ent->colormod[2] * r_lightmapintensity;
1306 static void R_MarkEntities (void)
1309 entity_render_t *ent;
1311 if (!r_drawentities.integer)
1314 r_refdef.worldentity->visframe = r_framecount;
1315 renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1316 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1318 // worldmodel can check visibility
1319 for (i = 0;i < r_refdef.numentities;i++)
1321 ent = r_refdef.entities[i];
1322 // some of the renderer still relies on origin...
1323 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1324 // some of the renderer still relies on scale...
1325 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1326 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)))
1328 ent->visframe = r_framecount;
1329 R_UpdateEntityLighting(ent);
1335 // no worldmodel or it can't check visibility
1336 for (i = 0;i < r_refdef.numentities;i++)
1338 ent = r_refdef.entities[i];
1339 // some of the renderer still relies on origin...
1340 Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
1341 // some of the renderer still relies on scale...
1342 ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
1343 if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
1345 ent->visframe = r_framecount;
1346 R_UpdateEntityLighting(ent);
1352 // only used if skyrendermasked, and normally returns false
1353 int R_DrawBrushModelsSky (void)
1356 entity_render_t *ent;
1358 if (!r_drawentities.integer)
1362 for (i = 0;i < r_refdef.numentities;i++)
1364 ent = r_refdef.entities[i];
1365 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
1367 ent->model->DrawSky(ent);
1374 void R_DrawNoModel(entity_render_t *ent);
1375 void R_DrawModels(void)
1378 entity_render_t *ent;
1380 if (!r_drawentities.integer)
1383 for (i = 0;i < r_refdef.numentities;i++)
1385 ent = r_refdef.entities[i];
1386 if (ent->visframe == r_framecount)
1388 renderstats.entities++;
1389 if (ent->model && ent->model->Draw != NULL)
1390 ent->model->Draw(ent);
1397 static void R_SetFrustum(void)
1399 // break apart the view matrix into vectors for various purposes
1400 Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
1401 VectorNegate(r_viewleft, r_viewright);
1404 frustum[0].normal[0] = 0 - 1.0 / r_refdef.frustum_x;
1405 frustum[0].normal[1] = 0 - 0;
1406 frustum[0].normal[2] = -1 - 0;
1407 frustum[1].normal[0] = 0 + 1.0 / r_refdef.frustum_x;
1408 frustum[1].normal[1] = 0 + 0;
1409 frustum[1].normal[2] = -1 + 0;
1410 frustum[2].normal[0] = 0 - 0;
1411 frustum[2].normal[1] = 0 - 1.0 / r_refdef.frustum_y;
1412 frustum[2].normal[2] = -1 - 0;
1413 frustum[3].normal[0] = 0 + 0;
1414 frustum[3].normal[1] = 0 + 1.0 / r_refdef.frustum_y;
1415 frustum[3].normal[2] = -1 + 0;
1419 zNear = r_nearclip.value;
1420 nudge = 1.0 - 1.0 / (1<<23);
1421 frustum[4].normal[0] = 0 - 0;
1422 frustum[4].normal[1] = 0 - 0;
1423 frustum[4].normal[2] = -1 - -nudge;
1424 frustum[4].dist = 0 - -2 * zNear * nudge;
1425 frustum[5].normal[0] = 0 + 0;
1426 frustum[5].normal[1] = 0 + 0;
1427 frustum[5].normal[2] = -1 + -nudge;
1428 frustum[5].dist = 0 + -2 * zNear * nudge;
1434 frustum[0].normal[0] = m[3] - m[0];
1435 frustum[0].normal[1] = m[7] - m[4];
1436 frustum[0].normal[2] = m[11] - m[8];
1437 frustum[0].dist = m[15] - m[12];
1439 frustum[1].normal[0] = m[3] + m[0];
1440 frustum[1].normal[1] = m[7] + m[4];
1441 frustum[1].normal[2] = m[11] + m[8];
1442 frustum[1].dist = m[15] + m[12];
1444 frustum[2].normal[0] = m[3] - m[1];
1445 frustum[2].normal[1] = m[7] - m[5];
1446 frustum[2].normal[2] = m[11] - m[9];
1447 frustum[2].dist = m[15] - m[13];
1449 frustum[3].normal[0] = m[3] + m[1];
1450 frustum[3].normal[1] = m[7] + m[5];
1451 frustum[3].normal[2] = m[11] + m[9];
1452 frustum[3].dist = m[15] + m[13];
1454 frustum[4].normal[0] = m[3] - m[2];
1455 frustum[4].normal[1] = m[7] - m[6];
1456 frustum[4].normal[2] = m[11] - m[10];
1457 frustum[4].dist = m[15] - m[14];
1459 frustum[5].normal[0] = m[3] + m[2];
1460 frustum[5].normal[1] = m[7] + m[6];
1461 frustum[5].normal[2] = m[11] + m[10];
1462 frustum[5].dist = m[15] + m[14];
1467 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_x, r_viewleft, frustum[0].normal);
1468 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_x, r_viewleft, frustum[1].normal);
1469 VectorMAM(1, r_viewforward, 1.0 / -r_refdef.frustum_y, r_viewup, frustum[2].normal);
1470 VectorMAM(1, r_viewforward, 1.0 / r_refdef.frustum_y, r_viewup, frustum[3].normal);
1471 VectorCopy(r_viewforward, frustum[4].normal);
1472 VectorNormalize(frustum[0].normal);
1473 VectorNormalize(frustum[1].normal);
1474 VectorNormalize(frustum[2].normal);
1475 VectorNormalize(frustum[3].normal);
1476 frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1477 frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1478 frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1479 frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1480 frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1481 PlaneClassify(&frustum[0]);
1482 PlaneClassify(&frustum[1]);
1483 PlaneClassify(&frustum[2]);
1484 PlaneClassify(&frustum[3]);
1485 PlaneClassify(&frustum[4]);
1487 // LordHavoc: note to all quake engine coders, Quake had a special case
1488 // for 90 degrees which assumed a square view (wrong), so I removed it,
1489 // Quake2 has it disabled as well.
1491 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1492 //RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_refdef.fov_x / 2));
1493 //frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
1494 //PlaneClassify(&frustum[0]);
1496 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1497 //RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_refdef.fov_x / 2));
1498 //frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
1499 //PlaneClassify(&frustum[1]);
1501 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1502 //RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_refdef.fov_y / 2));
1503 //frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
1504 //PlaneClassify(&frustum[2]);
1506 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1507 //RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_refdef.fov_y / 2));
1508 //frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
1509 //PlaneClassify(&frustum[3]);
1512 //VectorCopy(r_viewforward, frustum[4].normal);
1513 //frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + r_nearclip.value;
1514 //PlaneClassify(&frustum[4]);
1517 static void R_BlendView(void)
1519 int screenwidth, screenheight;
1524 // set the (poorly named) screenwidth and screenheight variables to
1525 // a power of 2 at least as large as the screen, these will define the
1526 // size of the texture to allocate
1527 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
1528 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
1530 doblend = r_refdef.viewblend[3] >= 0.01f;
1531 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;
1533 if (!dobloom && !doblend)
1536 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1538 GL_DepthTest(false);
1539 R_Mesh_Matrix(&identitymatrix);
1540 // vertex coordinates for a quad that covers the screen exactly
1541 varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
1542 varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
1543 varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
1544 varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
1547 int bloomwidth, bloomheight, x, dobloomblend, range;
1548 float xoffset, yoffset, r;
1549 renderstats.bloom++;
1550 // allocate textures as needed
1551 if (!r_bloom_texture_screen)
1552 r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1553 if (!r_bloom_texture_bloom)
1554 r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1555 // set bloomwidth and bloomheight to the bloom resolution that will be
1556 // used (often less than the screen resolution for faster rendering)
1557 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
1558 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
1559 // set up a texcoord array for the full resolution screen image
1560 // (we have to keep this around to copy back during final render)
1561 varray_texcoord2f[0][0] = 0;
1562 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
1563 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
1564 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
1565 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
1566 varray_texcoord2f[0][5] = 0;
1567 varray_texcoord2f[0][6] = 0;
1568 varray_texcoord2f[0][7] = 0;
1569 // set up a texcoord array for the reduced resolution bloom image
1570 // (which will be additive blended over the screen image)
1571 varray_texcoord2f[1][0] = 0;
1572 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
1573 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
1574 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
1575 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
1576 varray_texcoord2f[1][5] = 0;
1577 varray_texcoord2f[1][6] = 0;
1578 varray_texcoord2f[1][7] = 0;
1579 memset(&m, 0, sizeof(m));
1580 m.pointer_vertex = varray_vertex3f;
1581 m.pointer_texcoord[0] = varray_texcoord2f[0];
1582 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1584 // copy view into the full resolution screen image texture
1585 GL_ActiveTexture(0);
1586 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1587 renderstats.bloom_copypixels += r_view_width * r_view_height;
1588 // now scale it down to the bloom size and raise to a power of itself
1589 // to darken it (this leaves the really bright stuff bright, and
1590 // everything else becomes very dark)
1591 // TODO: optimize with multitexture or GLSL
1592 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1593 GL_BlendFunc(GL_ONE, GL_ZERO);
1594 GL_Color(1, 1, 1, 1);
1595 R_Mesh_Draw(0, 4, 2, polygonelements);
1596 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1597 // render multiple times with a multiply blendfunc to raise to a power
1598 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
1599 for (x = 1;x < r_bloom_power.integer;x++)
1601 R_Mesh_Draw(0, 4, 2, polygonelements);
1602 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1604 // we now have a darkened bloom image in the framebuffer, copy it into
1605 // the bloom image texture for more processing
1606 memset(&m, 0, sizeof(m));
1607 m.pointer_vertex = varray_vertex3f;
1608 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1609 m.pointer_texcoord[0] = varray_texcoord2f[2];
1611 GL_ActiveTexture(0);
1612 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1613 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1614 // blend on at multiple vertical offsets to achieve a vertical blur
1615 // TODO: do offset blends using GLSL
1616 range = r_bloom_blur.integer * bloomwidth / 320;
1617 GL_BlendFunc(GL_ONE, GL_ZERO);
1618 for (x = -range;x <= range;x++)
1620 xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1621 yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
1622 // compute a texcoord array with the specified x and y offset
1623 varray_texcoord2f[2][0] = xoffset+0;
1624 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1625 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1626 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1627 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1628 varray_texcoord2f[2][5] = yoffset+0;
1629 varray_texcoord2f[2][6] = xoffset+0;
1630 varray_texcoord2f[2][7] = yoffset+0;
1631 // this r value looks like a 'dot' particle, fading sharply to
1632 // black at the edges
1633 // (probably not realistic but looks good enough)
1634 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1637 GL_Color(r, r, r, 1);
1638 R_Mesh_Draw(0, 4, 2, polygonelements);
1639 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1640 GL_BlendFunc(GL_ONE, GL_ONE);
1642 // copy the vertically blurred bloom view to a texture
1643 GL_ActiveTexture(0);
1644 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1645 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1646 // blend the vertically blurred image at multiple offsets horizontally
1647 // to finish the blur effect
1648 // TODO: do offset blends using GLSL
1649 range = r_bloom_blur.integer * bloomwidth / 320;
1650 GL_BlendFunc(GL_ONE, GL_ZERO);
1651 for (x = -range;x <= range;x++)
1653 xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
1654 yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
1655 // compute a texcoord array with the specified x and y offset
1656 varray_texcoord2f[2][0] = xoffset+0;
1657 varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
1658 varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
1659 varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
1660 varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
1661 varray_texcoord2f[2][5] = yoffset+0;
1662 varray_texcoord2f[2][6] = xoffset+0;
1663 varray_texcoord2f[2][7] = yoffset+0;
1664 // this r value looks like a 'dot' particle, fading sharply to
1665 // black at the edges
1666 // (probably not realistic but looks good enough)
1667 r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
1670 GL_Color(r, r, r, 1);
1671 R_Mesh_Draw(0, 4, 2, polygonelements);
1672 renderstats.bloom_drawpixels += bloomwidth * bloomheight;
1673 GL_BlendFunc(GL_ONE, GL_ONE);
1675 // copy the blurred bloom view to a texture
1676 GL_ActiveTexture(0);
1677 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
1678 renderstats.bloom_copypixels += bloomwidth * bloomheight;
1679 // go back to full view area
1680 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1681 // put the original screen image back in place and blend the bloom
1683 memset(&m, 0, sizeof(m));
1684 m.pointer_vertex = varray_vertex3f;
1685 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
1686 m.pointer_texcoord[0] = varray_texcoord2f[0];
1688 dobloomblend = false;
1690 // do both in one pass if possible
1691 if (r_textureunits.integer >= 2 && gl_combine.integer)
1693 dobloomblend = false;
1694 m.texcombinergb[1] = GL_ADD;
1695 m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
1696 m.pointer_texcoord[1] = varray_texcoord2f[1];
1699 dobloomblend = true;
1702 GL_BlendFunc(GL_ONE, GL_ZERO);
1704 R_Mesh_Draw(0, 4, 2, polygonelements);
1705 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1706 // now blend on the bloom texture if multipass
1709 memset(&m, 0, sizeof(m));
1710 m.pointer_vertex = varray_vertex3f;
1711 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
1712 m.pointer_texcoord[0] = varray_texcoord2f[1];
1714 GL_BlendFunc(GL_ONE, GL_ONE);
1716 R_Mesh_Draw(0, 4, 2, polygonelements);
1717 renderstats.bloom_drawpixels += r_view_width * r_view_height;
1722 // apply a color tint to the whole view
1723 memset(&m, 0, sizeof(m));
1724 m.pointer_vertex = varray_vertex3f;
1726 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1727 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1728 R_Mesh_Draw(0, 4, 2, polygonelements);
1732 void R_RenderScene(void);
1734 matrix4x4_t r_waterscrollmatrix;
1741 void R_RenderView(void)
1743 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1744 return; //Host_Error ("R_RenderView: NULL worldmodel");
1746 r_view_width = bound(0, r_refdef.width, vid.width);
1747 r_view_height = bound(0, r_refdef.height, vid.height);
1749 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1750 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1752 r_view_matrix = r_refdef.viewentitymatrix;
1753 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1754 r_rtworld = r_shadow_realtime_world.integer;
1755 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1756 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1757 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1758 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1760 // GL is weird because it's bottom to top, r_view_y is top to bottom
1761 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1762 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1763 GL_ScissorTest(true);
1768 if (r_timereport_active)
1769 R_TimeReport("setup");
1771 qglDepthFunc(GL_LEQUAL);
1772 qglPolygonOffset(0, 0);
1773 qglEnable(GL_POLYGON_OFFSET_FILL);
1777 qglPolygonOffset(0, 0);
1778 qglDisable(GL_POLYGON_OFFSET_FILL);
1781 if (r_timereport_active)
1782 R_TimeReport("blendview");
1784 GL_Scissor(0, 0, vid.width, vid.height);
1785 GL_ScissorTest(false);
1789 void CSQC_R_ClearScreen (void)
1791 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1792 return; //Host_Error ("R_RenderView: NULL worldmodel");
1794 r_view_width = bound(0, r_refdef.width, vid.width);
1795 r_view_height = bound(0, r_refdef.height, vid.height);
1797 r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1798 r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1800 r_view_matrix = r_refdef.viewentitymatrix;
1801 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1802 r_rtworld = r_shadow_realtime_world.integer;
1803 r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1804 r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1805 r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1806 r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1808 // GL is weird because it's bottom to top, r_view_y is top to bottom
1809 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1810 GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1811 GL_ScissorTest(true);
1816 if (r_timereport_active)
1817 R_TimeReport("setup");
1821 void CSQC_R_RenderScene (void)
1823 qglDepthFunc(GL_LEQUAL);
1824 qglPolygonOffset(0, 0);
1825 qglEnable(GL_POLYGON_OFFSET_FILL);
1829 qglPolygonOffset(0, 0);
1830 qglDisable(GL_POLYGON_OFFSET_FILL);
1833 if (r_timereport_active)
1834 R_TimeReport("blendview");
1836 GL_Scissor(0, 0, vid.width, vid.height);
1837 GL_ScissorTest(false);
1840 extern void R_DrawLightningBeams (void);
1841 extern void VM_AddPolygonsToMeshQueue (void);
1842 void R_RenderScene(void)
1846 // don't let sound skip if going slow
1847 if (r_refdef.extraupdate)
1852 if (gl_support_fragment_shader)
1853 qglUseProgramObjectARB(0);
1855 R_MeshQueue_BeginScene();
1859 r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1860 nearclip = bound (0.001f, r_nearclip.value, r_farclip - 1.0f);
1862 if (r_rtworldshadows || r_rtdlightshadows)
1863 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.frustum_x, r_refdef.frustum_y, nearclip);
1865 GL_SetupView_Mode_Perspective(r_refdef.frustum_x, r_refdef.frustum_y, nearclip, r_farclip);
1867 GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1869 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);
1873 R_WorldVisibility();
1874 if (r_timereport_active)
1875 R_TimeReport("worldvis");
1878 if (r_timereport_active)
1879 R_TimeReport("markentity");
1881 R_Shadow_UpdateWorldLightSelection();
1883 for (r_showtrispass = 0;r_showtrispass <= (r_showtris.value > 0);r_showtrispass++)
1889 GL_BlendFunc(GL_ONE, GL_ONE);
1890 GL_DepthTest(!r_showdisabledepthtest.integer);
1891 GL_DepthMask(GL_FALSE);
1892 memset(&m, 0, sizeof(m));
1894 //qglEnable(GL_LINE_SMOOTH);
1895 qglEnable(GL_POLYGON_OFFSET_LINE);
1896 qglPolygonOffset(0, r_showtris_polygonoffset.value);
1900 if (cl.csqc_vidvars.drawworld)
1902 // don't let sound skip if going slow
1903 if (r_refdef.extraupdate)
1907 GL_ShowTrisColor(0.025, 0.025, 0, 1);
1908 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1910 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1911 if (r_timereport_active)
1912 R_TimeReport("worldsky");
1915 if (R_DrawBrushModelsSky() && r_timereport_active)
1916 R_TimeReport("bmodelsky");
1919 GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1920 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1922 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1923 if (r_timereport_active)
1924 R_TimeReport("world");
1928 // don't let sound skip if going slow
1929 if (r_refdef.extraupdate)
1933 GL_ShowTrisColor(0, 0.015, 0, 1);
1936 if (r_timereport_active)
1937 R_TimeReport("models");
1939 // don't let sound skip if going slow
1940 if (r_refdef.extraupdate)
1944 GL_ShowTrisColor(0, 0, 0.033, 1);
1945 R_ShadowVolumeLighting(false);
1946 if (r_timereport_active)
1947 R_TimeReport("rtlights");
1949 // don't let sound skip if going slow
1950 if (r_refdef.extraupdate)
1954 GL_ShowTrisColor(0.1, 0, 0, 1);
1956 if (cl.csqc_vidvars.drawworld)
1958 R_DrawLightningBeams();
1959 if (r_timereport_active)
1960 R_TimeReport("lightning");
1963 if (r_timereport_active)
1964 R_TimeReport("particles");
1967 if (r_timereport_active)
1968 R_TimeReport("explosions");
1971 R_MeshQueue_RenderTransparent();
1972 if (r_timereport_active)
1973 R_TimeReport("drawtrans");
1975 if (cl.csqc_vidvars.drawworld)
1978 if (r_timereport_active)
1979 R_TimeReport("coronas");
1981 if(cl.csqc_vidvars.drawcrosshair)
1983 R_DrawWorldCrosshair();
1984 if (r_timereport_active)
1985 R_TimeReport("crosshair");
1988 VM_AddPolygonsToMeshQueue();
1990 R_MeshQueue_Render();
1994 //qglDisable(GL_LINE_SMOOTH);
1995 qglDisable(GL_POLYGON_OFFSET_LINE);
2001 R_MeshQueue_EndScene();
2003 // don't let sound skip if going slow
2004 if (r_refdef.extraupdate)
2007 if (gl_support_fragment_shader)
2008 qglUseProgramObjectARB(0);
2012 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2015 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2017 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2018 GL_DepthMask(false);
2020 R_Mesh_Matrix(&identitymatrix);
2022 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2023 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2024 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2025 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2026 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2027 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2028 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2029 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2030 R_FillColors(color, 8, cr, cg, cb, ca);
2033 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2035 f2 = VERTEXFOGTABLE(VectorDistance(v, r_vieworigin));
2037 c[0] = c[0] * f1 + fogcolor[0] * f2;
2038 c[1] = c[1] * f1 + fogcolor[1] * f2;
2039 c[2] = c[2] * f1 + fogcolor[2] * f2;
2042 memset(&m, 0, sizeof(m));
2043 m.pointer_vertex = vertex3f;
2044 m.pointer_color = color;
2050 int nomodelelements[24] =
2062 float nomodelvertex3f[6*3] =
2072 float nomodelcolor4f[6*4] =
2074 0.0f, 0.0f, 0.5f, 1.0f,
2075 0.0f, 0.0f, 0.5f, 1.0f,
2076 0.0f, 0.5f, 0.0f, 1.0f,
2077 0.0f, 0.5f, 0.0f, 1.0f,
2078 0.5f, 0.0f, 0.0f, 1.0f,
2079 0.5f, 0.0f, 0.0f, 1.0f
2082 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
2088 R_Mesh_Matrix(&ent->matrix);
2090 memset(&m, 0, sizeof(m));
2091 m.pointer_vertex = nomodelvertex3f;
2093 if (ent->flags & EF_ADDITIVE)
2095 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2096 GL_DepthMask(false);
2098 else if (ent->alpha < 1)
2100 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2101 GL_DepthMask(false);
2105 GL_BlendFunc(GL_ONE, GL_ZERO);
2108 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2111 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2112 m.pointer_color = color4f;
2113 f2 = VERTEXFOGTABLE(VectorDistance(ent->origin, r_vieworigin));
2115 for (i = 0, c = color4f;i < 6;i++, c += 4)
2117 c[0] = (c[0] * f1 + fogcolor[0] * f2);
2118 c[1] = (c[1] * f1 + fogcolor[1] * f2);
2119 c[2] = (c[2] * f1 + fogcolor[2] * f2);
2123 else if (ent->alpha != 1)
2125 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2126 m.pointer_color = color4f;
2127 for (i = 0, c = color4f;i < 6;i++, c += 4)
2131 m.pointer_color = nomodelcolor4f;
2133 R_Mesh_Draw(0, 6, 8, nomodelelements);
2136 void R_DrawNoModel(entity_render_t *ent)
2138 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2139 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2141 // R_DrawNoModelCallback(ent, 0);
2144 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2146 vec3_t right1, right2, diff, normal;
2148 VectorSubtract (org2, org1, normal);
2150 // calculate 'right' vector for start
2151 VectorSubtract (r_vieworigin, org1, diff);
2152 CrossProduct (normal, diff, right1);
2153 VectorNormalize (right1);
2155 // calculate 'right' vector for end
2156 VectorSubtract (r_vieworigin, org2, diff);
2157 CrossProduct (normal, diff, right2);
2158 VectorNormalize (right2);
2160 vert[ 0] = org1[0] + width * right1[0];
2161 vert[ 1] = org1[1] + width * right1[1];
2162 vert[ 2] = org1[2] + width * right1[2];
2163 vert[ 3] = org1[0] - width * right1[0];
2164 vert[ 4] = org1[1] - width * right1[1];
2165 vert[ 5] = org1[2] - width * right1[2];
2166 vert[ 6] = org2[0] - width * right2[0];
2167 vert[ 7] = org2[1] - width * right2[1];
2168 vert[ 8] = org2[2] - width * right2[2];
2169 vert[ 9] = org2[0] + width * right2[0];
2170 vert[10] = org2[1] + width * right2[1];
2171 vert[11] = org2[2] + width * right2[2];
2174 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2176 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)
2178 float fog = 0.0f, ifog;
2182 fog = VERTEXFOGTABLE(VectorDistance(origin, r_vieworigin));
2185 R_Mesh_Matrix(&identitymatrix);
2186 GL_BlendFunc(blendfunc1, blendfunc2);
2187 GL_DepthMask(false);
2188 GL_DepthTest(!depthdisable);
2190 varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2191 varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2192 varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2193 varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2194 varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2195 varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2196 varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2197 varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2198 varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2199 varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2200 varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2201 varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2203 memset(&m, 0, sizeof(m));
2204 m.tex[0] = R_GetTexture(texture);
2205 m.pointer_texcoord[0] = spritetexcoord2f;
2206 m.pointer_vertex = varray_vertex3f;
2208 GL_Color(cr * ifog, cg * ifog, cb * ifog, ca);
2209 R_Mesh_Draw(0, 4, 2, polygonelements);
2211 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2213 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2214 GL_BlendFunc(blendfunc1, GL_ONE);
2215 GL_Color(fogcolor[0] * fog, fogcolor[1] * fog, fogcolor[2] * fog, ca);
2216 R_Mesh_Draw(0, 4, 2, polygonelements);
2220 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
2224 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2225 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2227 if (i == mesh->numvertices)
2229 if (mesh->numvertices < mesh->maxvertices)
2231 VectorCopy(v, vertex3f);
2232 mesh->numvertices++;
2234 return mesh->numvertices;
2240 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2244 element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2245 element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
2246 e = mesh->element3i + mesh->numtriangles * 3;
2247 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2249 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
2250 if (mesh->numtriangles < mesh->maxtriangles)
2255 mesh->numtriangles++;
2257 element[1] = element[2];
2261 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2263 int planenum, planenum2;
2266 mplane_t *plane, *plane2;
2267 float temppoints[2][256*3];
2268 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2272 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
2273 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2275 if (planenum2 == planenum)
2277 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);
2280 if (tempnumpoints < 3)
2282 // generate elements forming a triangle fan for this polygon
2283 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
2287 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)
2289 texturelayer_t *layer;
2290 layer = t->currentlayers + t->currentnumlayers++;
2292 layer->depthmask = depthmask;
2293 layer->blendfunc1 = blendfunc1;
2294 layer->blendfunc2 = blendfunc2;
2295 layer->texture = texture;
2296 layer->texmatrix = *matrix;
2297 layer->color[0] = r;
2298 layer->color[1] = g;
2299 layer->color[2] = b;
2300 layer->color[3] = a;
2303 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2305 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2306 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2309 texture_t *texture = t;
2310 model_t *model = ent->model;
2311 int s = ent->skinnum;
2312 if ((unsigned int)s >= (unsigned int)model->numskins)
2314 if (model->skinscenes)
2316 if (model->skinscenes[s].framecount > 1)
2317 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2319 s = model->skinscenes[s].firstframe;
2322 t = t + s * model->num_surfaces;
2324 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];
2325 texture->currentframe = t;
2328 t->currentmaterialflags = t->basematerialflags;
2329 t->currentalpha = ent->alpha;
2330 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2331 t->currentalpha *= r_wateralpha.value;
2332 if (!(ent->flags & RENDER_LIGHT))
2333 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2334 if (ent->effects & EF_ADDITIVE)
2335 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
2336 else if (t->currentalpha < 1)
2337 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
2338 if (ent->effects & EF_NODEPTHTEST)
2339 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2340 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2341 t->currenttexmatrix = r_waterscrollmatrix;
2343 t->currenttexmatrix = identitymatrix;
2345 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2346 t->basetexture = (!t->colormapping && t->skin.merged) ? t->skin.merged : t->skin.base;
2347 t->glosstexture = r_texture_white;
2348 t->specularpower = 8;
2349 t->specularscale = 0;
2350 if (r_shadow_gloss.integer > 0)
2354 if (r_shadow_glossintensity.value > 0)
2356 t->glosstexture = t->skin.gloss;
2357 t->specularscale = r_shadow_glossintensity.value;
2360 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2361 t->specularscale = r_shadow_gloss2intensity.value;
2364 t->currentnumlayers = 0;
2365 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2367 if (gl_lightmaps.integer)
2368 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2369 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2371 int blendfunc1, blendfunc2, depthmask;
2372 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2374 blendfunc1 = GL_SRC_ALPHA;
2375 blendfunc2 = GL_ONE;
2378 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2380 blendfunc1 = GL_SRC_ALPHA;
2381 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2386 blendfunc1 = GL_ONE;
2387 blendfunc2 = GL_ZERO;
2390 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2392 rtexture_t *currentbasetexture;
2394 if (fogenabled && (t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2395 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2396 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->skin.merged) ? t->skin.merged : t->skin.base;
2397 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2399 // fullbright is not affected by r_lightmapintensity
2400 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2401 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2402 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);
2403 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2404 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);
2410 // q3bsp has no lightmap updates, so the lightstylevalue that
2411 // would normally be baked into the lightmaptexture must be
2412 // applied to the color
2413 if (ent->model->type == mod_brushq3)
2414 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2415 colorscale *= r_lightmapintensity;
2416 if (r_textureunits.integer >= 2 && gl_combine.integer)
2417 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);
2418 else if ((t->currentmaterialflags & MATERIALFLAG_TRANSPARENT) == 0)
2419 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);
2421 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);
2422 if (r_ambient.value >= (1.0f/64.0f))
2423 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);
2424 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->skin.pants)
2426 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);
2427 if (r_ambient.value >= (1.0f/64.0f))
2428 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);
2430 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->skin.shirt)
2432 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);
2433 if (r_ambient.value >= (1.0f/64.0f))
2434 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);
2437 if (t->skin.glow != NULL)
2438 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->skin.glow, &t->currenttexmatrix, 1, 1, 1, t->currentalpha);
2439 if (fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2441 // if this is opaque use alpha blend which will darken the earlier
2444 // if this is an alpha blended material, all the earlier passes
2445 // were darkened by fog already, so we only need to add the fog
2446 // color ontop through the fog mask texture
2448 // if this is an additive blended material, all the earlier passes
2449 // were darkened by fog already, and we should not add fog color
2450 // (because the background was not darkened, there is no fog color
2451 // that was lost behind it).
2452 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);
2459 void R_UpdateAllTextureInfo(entity_render_t *ent)
2463 for (i = 0;i < ent->model->num_textures;i++)
2464 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2467 float *rsurface_vertex3f;
2468 float *rsurface_svector3f;
2469 float *rsurface_tvector3f;
2470 float *rsurface_normal3f;
2471 float *rsurface_lightmapcolor4f;
2473 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents)
2475 if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
2477 rsurface_vertex3f = varray_vertex3f;
2478 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
2479 if (generatetangents || (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)))
2481 rsurface_svector3f = varray_svector3f;
2482 rsurface_tvector3f = varray_tvector3f;
2483 rsurface_normal3f = varray_normal3f;
2484 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);
2488 rsurface_svector3f = NULL;
2489 rsurface_tvector3f = NULL;
2490 if (generatenormals)
2492 rsurface_normal3f = varray_normal3f;
2493 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);
2496 rsurface_normal3f = NULL;
2501 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
2502 rsurface_svector3f = surface->groupmesh->data_svector3f;
2503 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
2504 rsurface_normal3f = surface->groupmesh->data_normal3f;
2506 if (texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2509 float center[3], forward[3], right[3], up[3], v[4][3];
2510 matrix4x4_t matrix1, imatrix1;
2511 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
2512 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
2513 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
2514 // a single autosprite surface can contain multiple sprites...
2515 for (j = 0;j < surface->num_vertices - 3;j += 4)
2517 VectorClear(center);
2518 for (i = 0;i < 4;i++)
2519 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2520 VectorScale(center, 0.25f, center);
2521 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2522 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);
2523 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2524 for (i = 0;i < 4;i++)
2525 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2526 if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2528 forward[0] = modelorg[0] - center[0];
2529 forward[1] = modelorg[1] - center[1];
2531 VectorNormalize(forward);
2532 right[0] = forward[1];
2533 right[1] = -forward[0];
2535 VectorSet(up, 0, 0, 1);
2537 for (i = 0;i < 4;i++)
2538 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
2540 rsurface_vertex3f = varray_vertex3f;
2541 rsurface_svector3f = varray_svector3f;
2542 rsurface_tvector3f = varray_tvector3f;
2543 rsurface_normal3f = varray_normal3f;
2544 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);
2546 R_Mesh_VertexPointer(rsurface_vertex3f);
2549 static void RSurf_Draw(const msurface_t *surface)
2551 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2552 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2553 GL_LockArrays(0, 0);
2556 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)
2561 RSurf_SetVertexPointer(ent, texture, surface, modelorg, lightmode >= 2, false);
2565 vec4_t ambientcolor;
2566 vec3_t diffusecolor;
2568 VectorCopy(ent->modellight_lightdir, lightdir);
2569 ambientcolor[0] = ent->modellight_ambient[0] * r * 0.5f;
2570 ambientcolor[1] = ent->modellight_ambient[1] * g * 0.5f;
2571 ambientcolor[2] = ent->modellight_ambient[2] * b * 0.5f;
2572 diffusecolor[0] = ent->modellight_diffuse[0] * r * 0.5f;
2573 diffusecolor[1] = ent->modellight_diffuse[1] * g * 0.5f;
2574 diffusecolor[2] = ent->modellight_diffuse[2] * b * 0.5f;
2575 if (VectorLength2(diffusecolor) > 0)
2577 int numverts = surface->num_vertices;
2578 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2579 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2580 c = varray_color4f + 4 * surface->num_firstvertex;
2581 // q3-style directional shading
2582 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2584 if ((f = DotProduct(c2, lightdir)) > 0)
2586 VectorMA(ambientcolor, f, diffusecolor, c);
2590 VectorCopy4(ambientcolor, c);
2597 rsurface_lightmapcolor4f = varray_color4f;
2601 r = ambientcolor[0];
2602 g = ambientcolor[1];
2603 b = ambientcolor[2];
2604 rsurface_lightmapcolor4f = NULL;
2607 else if (lightmode >= 1)
2609 if (surface->lightmapinfo && surface->lightmapinfo->stainsamples)
2611 for (i = 0, c = varray_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2613 if (surface->lightmapinfo->samples)
2615 const unsigned char *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
2616 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2617 VectorScale(lm, scale, c);
2618 if (surface->lightmapinfo->styles[1] != 255)
2620 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2622 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2623 VectorMA(c, scale, lm, c);
2624 if (surface->lightmapinfo->styles[2] != 255)
2627 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
2628 VectorMA(c, scale, lm, c);
2629 if (surface->lightmapinfo->styles[3] != 255)
2632 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
2633 VectorMA(c, scale, lm, c);
2641 rsurface_lightmapcolor4f = varray_color4f;
2644 rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
2647 rsurface_lightmapcolor4f = NULL;
2650 if (rsurface_lightmapcolor4f)
2652 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)
2654 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2663 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)
2665 f = 1 - VERTEXFOGTABLE(VectorDistance(v, modelorg));
2672 rsurface_lightmapcolor4f = varray_color4f;
2674 if (applycolor && rsurface_lightmapcolor4f)
2676 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)
2683 rsurface_lightmapcolor4f = varray_color4f;
2685 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
2686 GL_Color(r, g, b, a);
2687 RSurf_Draw(surface);
2690 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2692 int texturesurfaceindex;
2694 const msurface_t *surface;
2695 qboolean applycolor;
2698 if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
2700 r_shadow_rtlight = NULL;
2701 renderstats.entities_surfaces += texturenumsurfaces;
2702 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2703 lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2704 GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
2705 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
2706 qglDisable(GL_CULL_FACE);
2707 if (texture->currentmaterialflags & MATERIALFLAG_SKY)
2709 // transparent sky would be ridiculous
2710 if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2715 skyrendernow = false;
2716 if (skyrendermasked)
2719 // restore entity matrix and GL_Color
2720 R_Mesh_Matrix(&ent->matrix);
2724 // LordHavoc: HalfLife maps have freaky skypolys...
2725 //if (!ent->model->brush.ishlbsp)
2727 if (skyrendermasked)
2729 // depth-only (masking)
2730 GL_ColorMask(0,0,0,0);
2731 // just to make sure that braindead drivers don't draw anything
2732 // despite that colormask...
2733 GL_BlendFunc(GL_ZERO, GL_ONE);
2738 GL_BlendFunc(GL_ONE, GL_ZERO);
2740 GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
2741 memset(&m, 0, sizeof(m));
2743 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2745 surface = texturesurfacelist[texturesurfaceindex];
2746 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2747 RSurf_Draw(surface);
2749 if (skyrendermasked)
2750 GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
2754 else if (r_glsl.integer && gl_support_fragment_shader)
2756 if (texture->currentmaterialflags & MATERIALFLAG_ADD)
2758 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2759 GL_DepthMask(false);
2761 else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
2763 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2764 GL_DepthMask(false);
2768 GL_BlendFunc(GL_ONE, GL_ZERO);
2772 memset(&m, 0, sizeof(m));
2774 GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], texture->currentalpha);
2775 R_SetupSurfaceShader(ent, texture, modelorg, vec3_origin, lightmode == 2);
2776 if (!r_glsl_permutation)
2780 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2782 surface = texturesurfacelist[texturesurfaceindex];
2783 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2784 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2785 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2786 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2787 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2788 RSurf_Draw(surface);
2793 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2795 surface = texturesurfacelist[texturesurfaceindex];
2796 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
2797 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2798 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
2799 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
2800 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
2801 R_Mesh_TexCoordPointer(4, 2, surface->groupmesh->data_texcoordlightmap2f);
2802 if (surface->lightmaptexture)
2804 R_Mesh_TexBind(7, R_GetTexture(surface->lightmaptexture));
2805 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2806 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2807 //R_Mesh_TexBind(8, R_GetTexture(surface->deluxemaptexture));
2808 R_Mesh_ColorPointer(NULL);
2812 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
2813 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
2814 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
2815 R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
2817 RSurf_Draw(surface);
2820 qglUseProgramObjectARB(0);
2822 else if (texture->currentnumlayers)
2825 texturelayer_t *layer;
2826 for (layerindex = 0, layer = texture->currentlayers;layerindex < texture->currentnumlayers;layerindex++, layer++)
2829 int layertexrgbscale;
2830 GL_DepthMask(layer->depthmask);
2831 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
2832 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
2834 layertexrgbscale = 4;
2835 VectorScale(layer->color, 0.25f, layercolor);
2837 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
2839 layertexrgbscale = 2;
2840 VectorScale(layer->color, 0.5f, layercolor);
2844 layertexrgbscale = 1;
2845 VectorScale(layer->color, 1.0f, layercolor);
2847 layercolor[3] = layer->color[3];
2848 GL_Color(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
2849 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
2850 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
2851 switch (layer->type)
2853 case TEXTURELAYERTYPE_LITTEXTURE_COMBINE:
2854 memset(&m, 0, sizeof(m));
2855 m.tex[1] = R_GetTexture(layer->texture);
2856 m.texmatrix[1] = layer->texmatrix;
2857 m.texrgbscale[1] = layertexrgbscale;
2858 m.pointer_color = varray_color4f;
2862 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2864 surface = texturesurfacelist[texturesurfaceindex];
2865 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2866 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2867 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2868 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2873 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2875 surface = texturesurfacelist[texturesurfaceindex];
2876 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2877 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
2878 if (surface->lightmaptexture)
2880 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2881 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2885 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2886 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2891 case TEXTURELAYERTYPE_LITTEXTURE_MULTIPASS:
2892 memset(&m, 0, sizeof(m));
2893 m.tex[0] = R_GetTexture(layer->texture);
2894 m.texmatrix[0] = layer->texmatrix;
2895 m.pointer_color = varray_color4f;
2896 m.texrgbscale[0] = layertexrgbscale;
2900 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2902 surface = texturesurfacelist[texturesurfaceindex];
2903 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2904 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2905 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 2, false, false);
2910 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2912 surface = texturesurfacelist[texturesurfaceindex];
2913 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
2914 if (surface->lightmaptexture)
2916 R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
2917 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 0, false, false);
2921 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
2922 RSurf_DrawLightmap(ent, texture, surface, modelorg, 1, 1, 1, 1, 1, false, false);
2926 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2927 memset(&m, 0, sizeof(m));
2928 m.tex[0] = R_GetTexture(layer->texture);
2929 m.texmatrix[0] = layer->texmatrix;
2930 m.pointer_color = varray_color4f;
2931 m.texrgbscale[0] = layertexrgbscale;
2933 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2935 surface = texturesurfacelist[texturesurfaceindex];
2936 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2937 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2940 case TEXTURELAYERTYPE_LITTEXTURE_VERTEX:
2941 memset(&m, 0, sizeof(m));
2942 m.tex[0] = R_GetTexture(layer->texture);
2943 m.texmatrix[0] = layer->texmatrix;
2944 m.texrgbscale[0] = layertexrgbscale;
2945 m.pointer_color = varray_color4f;
2949 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2951 surface = texturesurfacelist[texturesurfaceindex];
2952 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2953 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 2, applycolor, applyfog);
2958 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2960 surface = texturesurfacelist[texturesurfaceindex];
2961 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2962 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 1, applycolor, applyfog);
2966 case TEXTURELAYERTYPE_TEXTURE:
2967 memset(&m, 0, sizeof(m));
2968 m.tex[0] = R_GetTexture(layer->texture);
2969 m.texmatrix[0] = layer->texmatrix;
2970 m.pointer_color = varray_color4f;
2971 m.texrgbscale[0] = layertexrgbscale;
2973 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2975 surface = texturesurfacelist[texturesurfaceindex];
2976 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2977 RSurf_DrawLightmap(ent, texture, surface, modelorg, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
2980 case TEXTURELAYERTYPE_FOG:
2981 memset(&m, 0, sizeof(m));
2984 m.tex[0] = R_GetTexture(layer->texture);
2985 m.texmatrix[0] = layer->texmatrix;
2988 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2992 surface = texturesurfacelist[texturesurfaceindex];
2993 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
2995 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2996 R_Mesh_ColorPointer(varray_color4f);
2997 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)
2999 f = VERTEXFOGTABLE(VectorDistance(v, modelorg));
3000 c[0] = layercolor[0];
3001 c[1] = layercolor[1];
3002 c[2] = layercolor[2];
3003 c[3] = f * layercolor[3];
3005 RSurf_Draw(surface);
3009 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3011 // if trying to do overbright on first pass of an opaque surface
3012 // when combine is not supported, brighten as a post process
3013 if (layertexrgbscale > 1 && !gl_combine.integer && layer->depthmask)
3016 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3017 GL_Color(1, 1, 1, 1);
3018 memset(&m, 0, sizeof(m));
3020 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3022 surface = texturesurfacelist[texturesurfaceindex];
3023 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
3024 for (scale = 1;scale < layertexrgbscale;scale <<= 1)
3025 RSurf_Draw(surface);
3029 if (r_shownormals.integer && !r_showtrispass)
3033 GL_DepthTest(!r_showdisabledepthtest.integer);
3034 GL_DepthMask(texture->currentlayers->depthmask);
3035 GL_BlendFunc(texture->currentlayers->blendfunc1, texture->currentlayers->blendfunc2);
3036 memset(&m, 0, sizeof(m));
3038 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3040 surface = texturesurfacelist[texturesurfaceindex];
3041 RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, true);
3042 GL_Color(1, 0, 0, 1);
3044 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3046 VectorCopy(rsurface_vertex3f + k * 3, v);
3047 qglVertex3f(v[0], v[1], v[2]);
3048 VectorMA(v, 8, rsurface_svector3f + k * 3, v);
3049 qglVertex3f(v[0], v[1], v[2]);
3051 GL_Color(0, 0, 1, 1);
3052 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3054 VectorCopy(rsurface_vertex3f + k * 3, v);
3055 qglVertex3f(v[0], v[1], v[2]);
3056 VectorMA(v, 8, rsurface_tvector3f + k * 3, v);
3057 qglVertex3f(v[0], v[1], v[2]);
3059 GL_Color(0, 1, 0, 1);
3060 for (j = 0, k = surface->num_firstvertex;j < surface->num_vertices;j++, k++)
3062 VectorCopy(rsurface_vertex3f + k * 3, v);
3063 qglVertex3f(v[0], v[1], v[2]);
3064 VectorMA(v, 8, rsurface_normal3f + k * 3, v);
3065 qglVertex3f(v[0], v[1], v[2]);
3071 if ((texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (ent->flags & RENDER_NOCULLFACE))
3072 qglEnable(GL_CULL_FACE);
3075 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
3077 const msurface_t *surface = ent->model->data_surfaces + surfacenumber;
3081 texture = surface->texture;
3082 if (texture->basematerialflags & MATERIALFLAG_SKY)
3083 return; // transparent sky is too difficult
3084 R_UpdateTextureInfo(ent, texture);
3086 R_Mesh_Matrix(&ent->matrix);
3087 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3088 R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
3091 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
3093 int texturesurfaceindex;
3094 const msurface_t *surface;
3095 vec3_t tempcenter, center;
3096 if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
3098 // drawing sky transparently would be too difficult
3099 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
3101 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3103 surface = texturesurfacelist[texturesurfaceindex];
3104 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3105 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3106 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3107 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
3108 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_DrawSurface_TransparentCallback, ent, surface - ent->model->data_surfaces, r_shadow_rtlight);
3113 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
3116 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3117 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3119 int i, j, f, flagsmask;
3120 int counttriangles = 0;
3121 msurface_t *surface, **surfacechain;
3122 texture_t *t, *texture;
3123 model_t *model = ent->model;
3125 const int maxsurfacelist = 1024;
3126 int numsurfacelist = 0;
3127 const msurface_t *surfacelist[1024];
3130 R_Mesh_Matrix(&ent->matrix);
3131 Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
3133 // update light styles
3134 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3136 for (i = 0;i < model->brushq1.light_styles;i++)
3138 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3140 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3141 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3142 for (;(surface = *surfacechain);surfacechain++)
3143 surface->cached_dlight = true;
3148 R_UpdateAllTextureInfo(ent);
3149 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3154 if (ent == r_refdef.worldentity)
3156 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3158 if (!r_worldsurfacevisible[j])
3160 if (t != surface->texture)
3164 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3167 t = surface->texture;
3168 texture = t->currentframe;
3169 f = texture->currentmaterialflags & flagsmask;
3171 if (f && surface->num_triangles)
3173 // if lightmap parameters changed, rebuild lightmap texture
3174 if (surface->cached_dlight)
3175 R_BuildLightMap(ent, surface);
3176 // add face to draw list
3177 surfacelist[numsurfacelist++] = surface;
3178 counttriangles += surface->num_triangles;
3179 if (numsurfacelist >= maxsurfacelist)
3181 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3189 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3191 if (t != surface->texture)
3195 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3198 t = surface->texture;
3199 texture = t->currentframe;
3200 f = texture->currentmaterialflags & flagsmask;
3202 if (f && surface->num_triangles)
3204 // if lightmap parameters changed, rebuild lightmap texture
3205 if (surface->cached_dlight)
3206 R_BuildLightMap(ent, surface);
3207 // add face to draw list
3208 surfacelist[numsurfacelist++] = surface;
3209 counttriangles += surface->num_triangles;
3210 if (numsurfacelist >= maxsurfacelist)
3212 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3219 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
3220 if (!r_showtrispass)
3221 renderstats.entities_triangles += counttriangles;
3222 if (gl_support_fragment_shader)
3223 qglUseProgramObjectARB(0);