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;
34 r_viewcache_t r_viewcache;
36 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
37 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "shows surfaces as different colors"};
38 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
39 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
40 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"};
41 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"};
42 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
43 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"};
44 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"};
45 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"};
46 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
47 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
48 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
49 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
50 cvar_t r_fullbright = {0, "r_fullbright","0", "make everything bright cheat (not allowed in multiplayer)"};
51 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
52 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
53 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
54 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
55 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
56 cvar_t r_q1bsp_skymasking = {0, "r_qb1sp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
58 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
59 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
60 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
61 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
62 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
63 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
64 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
66 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)"};
68 cvar_t r_glsl = {0, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
69 cvar_t r_glsl_offsetmapping = {0, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
70 cvar_t r_glsl_offsetmapping_reliefmapping = {0, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
71 cvar_t r_glsl_offsetmapping_scale = {0, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
72 cvar_t r_glsl_deluxemapping = {0, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
74 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
75 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
76 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
78 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
79 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
80 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
81 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
82 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
83 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
84 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
86 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
87 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
88 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
90 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"};
92 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"};
94 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
96 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
97 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
99 typedef struct r_glsl_bloomshader_s
102 int loc_Texture_Bloom;
104 r_glsl_bloomshader_t;
106 static struct r_bloomstate_s
111 int bloomwidth, bloomheight;
113 int screentexturewidth, screentextureheight;
114 rtexture_t *texture_screen;
116 int bloomtexturewidth, bloomtextureheight;
117 rtexture_t *texture_bloom;
119 r_glsl_bloomshader_t *shader;
121 // arrays for rendering the screen passes
123 float screentexcoord2f[8];
124 float bloomtexcoord2f[8];
125 float offsettexcoord2f[8];
129 rtexture_t *r_texture_blanknormalmap;
130 rtexture_t *r_texture_white;
131 rtexture_t *r_texture_black;
132 rtexture_t *r_texture_notexture;
133 rtexture_t *r_texture_whitecube;
134 rtexture_t *r_texture_normalizationcube;
135 rtexture_t *r_texture_fogattenuation;
136 //rtexture_t *r_texture_fogintensity;
138 // information about each possible shader permutation
139 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
140 // currently selected permutation
141 r_glsl_permutation_t *r_glsl_permutation;
143 // temporary variable used by a macro
146 extern void R_DrawModelShadows(void);
148 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
151 for (i = 0;i < verts;i++)
162 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
165 for (i = 0;i < verts;i++)
175 // FIXME: move this to client?
178 if (gamemode == GAME_NEHAHRA)
180 Cvar_Set("gl_fogenable", "0");
181 Cvar_Set("gl_fogdensity", "0.2");
182 Cvar_Set("gl_fogred", "0.3");
183 Cvar_Set("gl_foggreen", "0.3");
184 Cvar_Set("gl_fogblue", "0.3");
186 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
189 // FIXME: move this to client?
190 void FOG_registercvars(void)
195 if (gamemode == GAME_NEHAHRA)
197 Cvar_RegisterVariable (&gl_fogenable);
198 Cvar_RegisterVariable (&gl_fogdensity);
199 Cvar_RegisterVariable (&gl_fogred);
200 Cvar_RegisterVariable (&gl_foggreen);
201 Cvar_RegisterVariable (&gl_fogblue);
202 Cvar_RegisterVariable (&gl_fogstart);
203 Cvar_RegisterVariable (&gl_fogend);
206 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
207 for (x = 0;x < FOGTABLEWIDTH;x++)
209 alpha = exp(r / ((double)x*(double)x));
210 if (x == FOGTABLEWIDTH - 1)
212 r_refdef.fogtable[x] = bound(0, alpha, 1);
216 static void R_BuildBlankTextures(void)
218 unsigned char data[4];
219 data[0] = 128; // normal X
220 data[1] = 128; // normal Y
221 data[2] = 255; // normal Z
222 data[3] = 128; // height
223 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
228 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
233 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
236 static void R_BuildNoTexture(void)
239 unsigned char pix[16][16][4];
240 // this makes a light grey/dark grey checkerboard texture
241 for (y = 0;y < 16;y++)
243 for (x = 0;x < 16;x++)
245 if ((y < 8) ^ (x < 8))
261 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
264 static void R_BuildWhiteCube(void)
266 unsigned char data[6*1*1*4];
267 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
268 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
269 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
270 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
271 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
272 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
273 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
276 static void R_BuildNormalizationCube(void)
280 vec_t s, t, intensity;
282 unsigned char data[6][NORMSIZE][NORMSIZE][4];
283 for (side = 0;side < 6;side++)
285 for (y = 0;y < NORMSIZE;y++)
287 for (x = 0;x < NORMSIZE;x++)
289 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
290 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
325 intensity = 127.0f / sqrt(DotProduct(v, v));
326 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
327 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
328 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
329 data[side][y][x][3] = 255;
333 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
336 static void R_BuildFogTexture(void)
341 unsigned char data1[FOGWIDTH][4];
342 //unsigned char data2[FOGWIDTH][4];
343 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
344 for (x = 0;x < FOGWIDTH;x++)
346 alpha = exp(r / ((double)x*(double)x));
347 if (x == FOGWIDTH - 1)
349 b = (int)(256.0 * alpha);
350 b = bound(0, b, 255);
351 data1[x][0] = 255 - b;
352 data1[x][1] = 255 - b;
353 data1[x][2] = 255 - b;
360 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
361 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
364 static const char *builtinshaderstring =
365 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
366 "// written by Forest 'LordHavoc' Hale\n"
368 "// common definitions between vertex shader and fragment shader:\n"
370 "#ifdef __GLSL_CG_DATA_TYPES\n"
371 "#define myhalf half\n"
372 "#define myhvec2 hvec2\n"
373 "#define myhvec3 hvec3\n"
374 "#define myhvec4 hvec4\n"
376 "#define myhalf float\n"
377 "#define myhvec2 vec2\n"
378 "#define myhvec3 vec3\n"
379 "#define myhvec4 vec4\n"
382 "varying vec2 TexCoord;\n"
383 "varying vec2 TexCoordLightmap;\n"
385 "varying vec3 CubeVector;\n"
386 "varying vec3 LightVector;\n"
387 "varying vec3 EyeVector;\n"
389 "varying vec3 EyeVectorModelSpace;\n"
392 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
393 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
394 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
399 "// vertex shader specific:\n"
400 "#ifdef VERTEX_SHADER\n"
402 "uniform vec3 LightPosition;\n"
403 "uniform vec3 EyePosition;\n"
404 "uniform vec3 LightDir;\n"
406 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
410 " gl_FrontColor = gl_Color;\n"
411 " // copy the surface texcoord\n"
412 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
413 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
414 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
417 "#ifdef MODE_LIGHTSOURCE\n"
418 " // transform vertex position into light attenuation/cubemap space\n"
419 " // (-1 to +1 across the light box)\n"
420 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
422 " // transform unnormalized light direction into tangent space\n"
423 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
424 " // normalize it per pixel)\n"
425 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
426 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
427 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
428 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
431 "#ifdef MODE_LIGHTDIRECTION\n"
432 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
433 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
434 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
437 " // transform unnormalized eye direction into tangent space\n"
439 " vec3 EyeVectorModelSpace;\n"
441 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
442 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
443 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
444 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
446 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
447 " VectorS = gl_MultiTexCoord1.xyz;\n"
448 " VectorT = gl_MultiTexCoord2.xyz;\n"
449 " VectorR = gl_MultiTexCoord3.xyz;\n"
452 " // transform vertex to camera space, using ftransform to match non-VS\n"
454 " gl_Position = ftransform();\n"
457 "#endif // VERTEX_SHADER\n"
462 "// fragment shader specific:\n"
463 "#ifdef FRAGMENT_SHADER\n"
465 "uniform sampler2D Texture_Normal;\n"
466 "uniform sampler2D Texture_Color;\n"
467 "uniform sampler2D Texture_Gloss;\n"
468 "uniform samplerCube Texture_Cube;\n"
469 "uniform sampler2D Texture_FogMask;\n"
470 "uniform sampler2D Texture_Pants;\n"
471 "uniform sampler2D Texture_Shirt;\n"
472 "uniform sampler2D Texture_Lightmap;\n"
473 "uniform sampler2D Texture_Deluxemap;\n"
474 "uniform sampler2D Texture_Glow;\n"
476 "uniform myhvec3 LightColor;\n"
477 "uniform myhvec3 AmbientColor;\n"
478 "uniform myhvec3 DiffuseColor;\n"
479 "uniform myhvec3 SpecularColor;\n"
480 "uniform myhvec3 Color_Pants;\n"
481 "uniform myhvec3 Color_Shirt;\n"
482 "uniform myhvec3 FogColor;\n"
484 "uniform myhalf GlowScale;\n"
485 "uniform myhalf SceneBrightness;\n"
487 "uniform float OffsetMapping_Scale;\n"
488 "uniform float OffsetMapping_Bias;\n"
489 "uniform float FogRangeRecip;\n"
491 "uniform myhalf AmbientScale;\n"
492 "uniform myhalf DiffuseScale;\n"
493 "uniform myhalf SpecularScale;\n"
494 "uniform myhalf SpecularPower;\n"
498 " // apply offsetmapping\n"
499 "#ifdef USEOFFSETMAPPING\n"
500 " vec2 TexCoordOffset = TexCoord;\n"
501 "#define TexCoord TexCoordOffset\n"
503 " vec3 eyedir = vec3(normalize(EyeVector));\n"
504 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
505 " depthbias = 1.0 - depthbias * depthbias;\n"
507 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
508 " // 14 sample relief mapping: linear search and then binary search\n"
509 " //vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
510 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
511 " vec3 OffsetVector = vec3(eyedir.xy * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
512 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
513 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
514 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
515 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
516 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
517 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
518 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
519 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
520 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
521 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
522 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
523 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
524 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
525 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
526 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
527 " TexCoord = RT.xy;\n"
529 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
530 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
531 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
532 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
533 " //TexCoord += OffsetVector * 3.0;\n"
534 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
535 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
536 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
538 " // 10 sample offset mapping\n"
539 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
540 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
541 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1);\n"
542 " //TexCoord += OffsetVector * 3.0;\n"
543 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
544 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
545 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
546 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
547 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
548 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
549 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
550 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
551 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
552 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
554 " // parallax mapping as described in the paper\n"
555 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
556 " // The paper provides code in the ARB fragment program assembly language\n"
557 " // I translated it to GLSL but may have done something wrong - SavageX\n"
558 " // LordHavoc: removed bias and simplified to one line\n"
559 " // LordHavoc: this is just a single sample offsetmapping...\n"
560 " TexCoordOffset += vec2(eyedir.x, -1.0 * eyedir.y) * OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).a;\n"
562 " // parallax mapping as described in the paper\n"
563 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
564 " // The paper provides code in the ARB fragment program assembly language\n"
565 " // I translated it to GLSL but may have done something wrong - SavageX\n"
566 " float height = texture2D(Texture_Normal, TexCoord).a;\n"
567 " height = (height - 0.5) * OffsetMapping_Scale; // bias and scale\n"
568 " TexCoordOffset += height * vec2(eyedir.x, -1.0 * eyedir.y);\n"
572 " // combine the diffuse textures (base, pants, shirt)\n"
573 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
574 "#ifdef USECOLORMAPPING\n"
575 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
581 "#ifdef MODE_LIGHTSOURCE\n"
584 " // get the surface normal and light normal\n"
585 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
586 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
588 " // calculate directional shading\n"
589 " color.rgb *= AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
590 "#ifdef USESPECULAR\n"
591 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
592 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
595 "#ifdef USECUBEFILTER\n"
596 " // apply light cubemap filter\n"
597 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
598 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
601 " // apply light color\n"
602 " color.rgb *= LightColor;\n"
604 " // apply attenuation\n"
606 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
607 " // center and sharp falloff at the edge, this is about the most efficient\n"
608 " // we can get away with as far as providing illumination.\n"
610 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
611 " // provide significant illumination, large = slow = pain.\n"
612 " color.rgb *= myhalf(max(1.0 - dot(CubeVector, CubeVector), 0.0));\n"
617 "#elif defined(MODE_LIGHTDIRECTION)\n"
618 " // directional model lighting\n"
620 " // get the surface normal and light normal\n"
621 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
622 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
624 " // calculate directional shading\n"
625 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
626 "#ifdef USESPECULAR\n"
627 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
628 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
634 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
635 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
637 " // get the surface normal and light normal\n"
638 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
640 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
641 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
642 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
644 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
646 " // calculate directional shading\n"
647 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
648 "#ifdef USESPECULAR\n"
649 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
650 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
653 " // apply lightmap color\n"
654 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
657 "#else // MODE none (lightmap)\n"
658 " // apply lightmap color\n"
659 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
662 " color *= myhvec4(gl_Color);\n"
665 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
670 " myhalf fog = myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x);\n"
671 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
674 " color.rgb *= SceneBrightness;\n"
676 " gl_FragColor = vec4(color);\n"
679 "#endif // FRAGMENT_SHADER\n"
682 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
683 const char *permutationinfo[][2] =
685 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
686 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
687 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
688 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
689 {"#define USEGLOW\n", " glow"},
690 {"#define USEFOG\n", " fog"},
691 {"#define USECOLORMAPPING\n", " colormapping"},
692 {"#define USESPECULAR\n", " specular"},
693 {"#define USECUBEFILTER\n", " cubefilter"},
694 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
695 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
699 void R_GLSL_CompilePermutation(int permutation)
702 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
703 int vertstrings_count;
704 int fragstrings_count;
706 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
707 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
708 char permutationname[256];
712 vertstrings_list[0] = "#define VERTEX_SHADER\n";
713 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
714 vertstrings_count = 1;
715 fragstrings_count = 1;
716 permutationname[0] = 0;
717 for (i = 0;permutationinfo[i][0];i++)
719 if (permutation & (1<<i))
721 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
722 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
723 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
727 // keep line numbers correct
728 vertstrings_list[vertstrings_count++] = "\n";
729 fragstrings_list[fragstrings_count++] = "\n";
732 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
735 Con_DPrintf("GLSL shader text loaded from disk\n");
736 vertstrings_list[vertstrings_count++] = shaderstring;
737 fragstrings_list[fragstrings_count++] = shaderstring;
741 vertstrings_list[vertstrings_count++] = builtinshaderstring;
742 fragstrings_list[fragstrings_count++] = builtinshaderstring;
744 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
748 qglUseProgramObjectARB(p->program);CHECKGLERROR
749 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
750 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
751 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
752 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
753 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
754 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
755 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
756 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
757 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
758 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
759 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
760 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
761 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
762 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
763 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
764 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
765 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
766 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
767 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
768 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
769 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
770 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
771 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
772 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
773 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
774 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
775 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
776 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
777 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
778 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
779 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
780 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
781 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
782 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
783 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
784 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
785 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
786 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
788 qglUseProgramObjectARB(0);CHECKGLERROR
791 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
793 Mem_Free(shaderstring);
796 void R_GLSL_Restart_f(void)
799 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
800 if (r_glsl_permutations[i].program)
801 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
802 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
805 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
807 // select a permutation of the lighting shader appropriate to this
808 // combination of texture, entity, light source, and fogging, only use the
809 // minimum features necessary to avoid wasting rendering time in the
810 // fragment shader on features that are not being used
812 float specularscale = rsurface_texture->specularscale;
813 r_glsl_permutation = NULL;
814 if (r_shadow_rtlight)
816 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
817 specularscale *= r_shadow_rtlight->specularscale;
818 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
819 permutation |= SHADERPERMUTATION_CUBEFILTER;
823 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
826 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
827 else if (r_glsl_deluxemapping.integer >= 1 && rsurface_lightmaptexture)
829 if (r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
831 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
832 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
834 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
836 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
837 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
840 if (rsurface_texture->currentskinframe->glow)
841 permutation |= SHADERPERMUTATION_GLOW;
843 if (specularscale > 0)
844 permutation |= SHADERPERMUTATION_SPECULAR;
845 if (r_refdef.fogenabled)
846 permutation |= SHADERPERMUTATION_FOG;
847 if (rsurface_texture->colormapping)
848 permutation |= SHADERPERMUTATION_COLORMAPPING;
849 if (r_glsl_offsetmapping.integer)
851 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
852 if (r_glsl_offsetmapping_reliefmapping.integer)
853 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
855 if (!r_glsl_permutations[permutation].program)
857 if (!r_glsl_permutations[permutation].compiled)
858 R_GLSL_CompilePermutation(permutation);
859 if (!r_glsl_permutations[permutation].program)
861 // remove features until we find a valid permutation
863 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
865 // reduce i more quickly whenever it would not remove any bits
869 if (!r_glsl_permutations[permutation].compiled)
870 R_GLSL_CompilePermutation(permutation);
871 if (r_glsl_permutations[permutation].program)
874 return 0; // utterly failed
878 r_glsl_permutation = r_glsl_permutations + permutation;
880 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
881 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
882 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
884 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
885 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]);
886 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
887 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
888 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
889 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
891 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
893 if (r_glsl_permutation->loc_AmbientColor >= 0)
894 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
895 if (r_glsl_permutation->loc_DiffuseColor >= 0)
896 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
897 if (r_glsl_permutation->loc_SpecularColor >= 0)
898 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface_entity->modellight_diffuse[0] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[1] * rsurface_texture->specularscale, rsurface_entity->modellight_diffuse[2] * rsurface_texture->specularscale);
899 if (r_glsl_permutation->loc_LightDir >= 0)
900 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
904 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
905 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
906 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
908 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
909 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
910 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
911 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
912 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
913 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
914 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
915 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
916 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
917 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
918 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
919 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
920 if (r_glsl_permutation->loc_FogColor >= 0)
922 // additive passes are only darkened by fog, not tinted
923 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
924 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
926 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
928 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
929 if (r_glsl_permutation->loc_Color_Pants >= 0)
931 if (rsurface_texture->currentskinframe->pants)
932 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
934 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
936 if (r_glsl_permutation->loc_Color_Shirt >= 0)
938 if (rsurface_texture->currentskinframe->shirt)
939 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
941 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
943 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
944 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
945 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
950 void R_SwitchSurfaceShader(int permutation)
952 if (r_glsl_permutation != r_glsl_permutations + permutation)
954 r_glsl_permutation = r_glsl_permutations + permutation;
956 qglUseProgramObjectARB(r_glsl_permutation->program);
961 void gl_main_start(void)
963 r_main_texturepool = R_AllocTexturePool();
964 R_BuildBlankTextures();
966 if (gl_texturecubemap)
969 R_BuildNormalizationCube();
972 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
973 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
976 void gl_main_shutdown(void)
978 R_FreeTexturePool(&r_main_texturepool);
979 r_texture_blanknormalmap = NULL;
980 r_texture_white = NULL;
981 r_texture_black = NULL;
982 r_texture_whitecube = NULL;
983 r_texture_normalizationcube = NULL;
984 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
988 extern void CL_ParseEntityLump(char *entitystring);
989 void gl_main_newmap(void)
991 // FIXME: move this code to client
993 char *entities, entname[MAX_QPATH];
996 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
997 l = (int)strlen(entname) - 4;
998 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1000 memcpy(entname + l, ".ent", 5);
1001 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1003 CL_ParseEntityLump(entities);
1008 if (cl.worldmodel->brush.entities)
1009 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1013 void GL_Main_Init(void)
1015 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1017 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1018 FOG_registercvars(); // FIXME: move this fog stuff to client?
1019 Cvar_RegisterVariable(&r_nearclip);
1020 Cvar_RegisterVariable(&r_showsurfaces);
1021 Cvar_RegisterVariable(&r_showtris);
1022 Cvar_RegisterVariable(&r_shownormals);
1023 Cvar_RegisterVariable(&r_showlighting);
1024 Cvar_RegisterVariable(&r_showshadowvolumes);
1025 Cvar_RegisterVariable(&r_showcollisionbrushes);
1026 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1027 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1028 Cvar_RegisterVariable(&r_showdisabledepthtest);
1029 Cvar_RegisterVariable(&r_drawportals);
1030 Cvar_RegisterVariable(&r_drawentities);
1031 Cvar_RegisterVariable(&r_drawviewmodel);
1032 Cvar_RegisterVariable(&r_speeds);
1033 Cvar_RegisterVariable(&r_fullbrights);
1034 Cvar_RegisterVariable(&r_wateralpha);
1035 Cvar_RegisterVariable(&r_dynamic);
1036 Cvar_RegisterVariable(&r_fullbright);
1037 Cvar_RegisterVariable(&r_shadows);
1038 Cvar_RegisterVariable(&r_shadows_throwdistance);
1039 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1040 Cvar_RegisterVariable(&r_textureunits);
1041 Cvar_RegisterVariable(&r_glsl);
1042 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1043 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1044 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1045 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1046 Cvar_RegisterVariable(&r_lerpsprites);
1047 Cvar_RegisterVariable(&r_lerpmodels);
1048 Cvar_RegisterVariable(&r_waterscroll);
1049 Cvar_RegisterVariable(&r_bloom);
1050 Cvar_RegisterVariable(&r_bloom_colorscale);
1051 Cvar_RegisterVariable(&r_bloom_brighten);
1052 Cvar_RegisterVariable(&r_bloom_blur);
1053 Cvar_RegisterVariable(&r_bloom_resolution);
1054 Cvar_RegisterVariable(&r_bloom_colorexponent);
1055 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1056 Cvar_RegisterVariable(&r_hdr);
1057 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1058 Cvar_RegisterVariable(&r_hdr_glowintensity);
1059 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1060 Cvar_RegisterVariable(&developer_texturelogging);
1061 Cvar_RegisterVariable(&gl_lightmaps);
1062 Cvar_RegisterVariable(&r_test);
1063 Cvar_RegisterVariable(&r_batchmode);
1064 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1065 Cvar_SetValue("r_fullbrights", 0);
1066 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1069 extern void R_Textures_Init(void);
1070 extern void GL_Draw_Init(void);
1071 extern void GL_Main_Init(void);
1072 extern void R_Shadow_Init(void);
1073 extern void R_Sky_Init(void);
1074 extern void GL_Surf_Init(void);
1075 extern void R_Light_Init(void);
1076 extern void R_Particles_Init(void);
1077 extern void R_Explosion_Init(void);
1078 extern void gl_backend_init(void);
1079 extern void Sbar_Init(void);
1080 extern void R_LightningBeams_Init(void);
1081 extern void Mod_RenderInit(void);
1083 void Render_Init(void)
1096 R_LightningBeams_Init();
1105 extern char *ENGINE_EXTENSIONS;
1108 VID_CheckExtensions();
1110 // LordHavoc: report supported extensions
1111 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1113 // clear to black (loading plaque will be seen over this)
1115 qglClearColor(0,0,0,1);CHECKGLERROR
1116 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1119 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1123 for (i = 0;i < 4;i++)
1125 p = r_view.frustum + i;
1130 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1134 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1138 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1142 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1146 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1150 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1154 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1158 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1166 //==================================================================================
1168 static void R_UpdateEntityLighting(entity_render_t *ent)
1170 vec3_t tempdiffusenormal;
1172 // fetch the lighting from the worldmodel data
1173 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));
1174 VectorClear(ent->modellight_diffuse);
1175 VectorClear(tempdiffusenormal);
1176 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1179 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1180 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1183 VectorSet(ent->modellight_ambient, 1, 1, 1);
1185 // move the light direction into modelspace coordinates for lighting code
1186 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1187 VectorNormalize(ent->modellight_lightdir);
1189 // scale ambient and directional light contributions according to rendering variables
1190 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1191 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1192 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1193 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1194 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1195 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1198 static void R_View_UpdateEntityVisible (void)
1201 entity_render_t *ent;
1203 if (!r_drawentities.integer)
1206 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1207 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1209 // worldmodel can check visibility
1210 for (i = 0;i < r_refdef.numentities;i++)
1212 ent = r_refdef.entities[i];
1213 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
1218 // no worldmodel or it can't check visibility
1219 for (i = 0;i < r_refdef.numentities;i++)
1221 ent = r_refdef.entities[i];
1222 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1226 // update entity lighting (even on hidden entities for r_shadows)
1227 for (i = 0;i < r_refdef.numentities;i++)
1228 R_UpdateEntityLighting(r_refdef.entities[i]);
1231 // only used if skyrendermasked, and normally returns false
1232 int R_DrawBrushModelsSky (void)
1235 entity_render_t *ent;
1237 if (!r_drawentities.integer)
1241 for (i = 0;i < r_refdef.numentities;i++)
1243 if (!r_viewcache.entityvisible[i])
1245 ent = r_refdef.entities[i];
1246 if (!ent->model || !ent->model->DrawSky)
1248 ent->model->DrawSky(ent);
1254 void R_DrawNoModel(entity_render_t *ent);
1255 void R_DrawModels(void)
1258 entity_render_t *ent;
1260 if (!r_drawentities.integer)
1263 for (i = 0;i < r_refdef.numentities;i++)
1265 if (!r_viewcache.entityvisible[i])
1267 ent = r_refdef.entities[i];
1268 r_refdef.stats.entities++;
1269 if (ent->model && ent->model->Draw != NULL)
1270 ent->model->Draw(ent);
1276 static void R_View_SetFrustum(void)
1278 // break apart the view matrix into vectors for various purposes
1279 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1280 VectorNegate(r_view.left, r_view.right);
1283 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1284 r_view.frustum[0].normal[1] = 0 - 0;
1285 r_view.frustum[0].normal[2] = -1 - 0;
1286 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1287 r_view.frustum[1].normal[1] = 0 + 0;
1288 r_view.frustum[1].normal[2] = -1 + 0;
1289 r_view.frustum[2].normal[0] = 0 - 0;
1290 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1291 r_view.frustum[2].normal[2] = -1 - 0;
1292 r_view.frustum[3].normal[0] = 0 + 0;
1293 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1294 r_view.frustum[3].normal[2] = -1 + 0;
1298 zNear = r_refdef.nearclip;
1299 nudge = 1.0 - 1.0 / (1<<23);
1300 r_view.frustum[4].normal[0] = 0 - 0;
1301 r_view.frustum[4].normal[1] = 0 - 0;
1302 r_view.frustum[4].normal[2] = -1 - -nudge;
1303 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1304 r_view.frustum[5].normal[0] = 0 + 0;
1305 r_view.frustum[5].normal[1] = 0 + 0;
1306 r_view.frustum[5].normal[2] = -1 + -nudge;
1307 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1313 r_view.frustum[0].normal[0] = m[3] - m[0];
1314 r_view.frustum[0].normal[1] = m[7] - m[4];
1315 r_view.frustum[0].normal[2] = m[11] - m[8];
1316 r_view.frustum[0].dist = m[15] - m[12];
1318 r_view.frustum[1].normal[0] = m[3] + m[0];
1319 r_view.frustum[1].normal[1] = m[7] + m[4];
1320 r_view.frustum[1].normal[2] = m[11] + m[8];
1321 r_view.frustum[1].dist = m[15] + m[12];
1323 r_view.frustum[2].normal[0] = m[3] - m[1];
1324 r_view.frustum[2].normal[1] = m[7] - m[5];
1325 r_view.frustum[2].normal[2] = m[11] - m[9];
1326 r_view.frustum[2].dist = m[15] - m[13];
1328 r_view.frustum[3].normal[0] = m[3] + m[1];
1329 r_view.frustum[3].normal[1] = m[7] + m[5];
1330 r_view.frustum[3].normal[2] = m[11] + m[9];
1331 r_view.frustum[3].dist = m[15] + m[13];
1333 r_view.frustum[4].normal[0] = m[3] - m[2];
1334 r_view.frustum[4].normal[1] = m[7] - m[6];
1335 r_view.frustum[4].normal[2] = m[11] - m[10];
1336 r_view.frustum[4].dist = m[15] - m[14];
1338 r_view.frustum[5].normal[0] = m[3] + m[2];
1339 r_view.frustum[5].normal[1] = m[7] + m[6];
1340 r_view.frustum[5].normal[2] = m[11] + m[10];
1341 r_view.frustum[5].dist = m[15] + m[14];
1346 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
1347 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
1348 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
1349 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
1350 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1351 VectorNormalize(r_view.frustum[0].normal);
1352 VectorNormalize(r_view.frustum[1].normal);
1353 VectorNormalize(r_view.frustum[2].normal);
1354 VectorNormalize(r_view.frustum[3].normal);
1355 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1356 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1357 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1358 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1359 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1360 PlaneClassify(&r_view.frustum[0]);
1361 PlaneClassify(&r_view.frustum[1]);
1362 PlaneClassify(&r_view.frustum[2]);
1363 PlaneClassify(&r_view.frustum[3]);
1364 PlaneClassify(&r_view.frustum[4]);
1366 // LordHavoc: note to all quake engine coders, Quake had a special case
1367 // for 90 degrees which assumed a square view (wrong), so I removed it,
1368 // Quake2 has it disabled as well.
1370 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1371 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1372 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1373 //PlaneClassify(&frustum[0]);
1375 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1376 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1377 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1378 //PlaneClassify(&frustum[1]);
1380 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1381 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1382 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1383 //PlaneClassify(&frustum[2]);
1385 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1386 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1387 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1388 //PlaneClassify(&frustum[3]);
1391 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1392 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1393 //PlaneClassify(&frustum[4]);
1396 void R_View_Update(void)
1398 R_View_SetFrustum();
1399 R_View_WorldVisibility();
1400 R_View_UpdateEntityVisible();
1403 void R_ResetViewRendering(void)
1405 if (gl_support_fragment_shader)
1407 qglUseProgramObjectARB(0);CHECKGLERROR
1410 // GL is weird because it's bottom to top, r_view.y is top to bottom
1411 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1412 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1413 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1414 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1415 GL_ScissorTest(false);
1416 GL_DepthMask(false);
1417 GL_DepthTest(false);
1418 R_Mesh_Matrix(&identitymatrix);
1419 R_Mesh_ResetTextureState();
1423 R_Bloom_SetupShader(
1425 "// written by Forest 'LordHavoc' Hale\n"
1427 "// common definitions between vertex shader and fragment shader:\n"
1429 "#ifdef __GLSL_CG_DATA_TYPES\n"
1430 "#define myhalf half\n"
1431 "#define myhvec2 hvec2\n"
1432 "#define myhvec3 hvec3\n"
1433 "#define myhvec4 hvec4\n"
1435 "#define myhalf float\n"
1436 "#define myhvec2 vec2\n"
1437 "#define myhvec3 vec3\n"
1438 "#define myhvec4 vec4\n"
1441 "varying vec2 ScreenTexCoord;\n"
1442 "varying vec2 BloomTexCoord;\n"
1447 "// vertex shader specific:\n"
1448 "#ifdef VERTEX_SHADER\n"
1452 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
1453 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
1454 " // transform vertex to camera space, using ftransform to match non-VS\n"
1456 " gl_Position = ftransform();\n"
1459 "#endif // VERTEX_SHADER\n"
1464 "// fragment shader specific:\n"
1465 "#ifdef FRAGMENT_SHADER\n"
1470 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
1471 " for (x = -BLUR_X;x <= BLUR_X;x++)
1472 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1473 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1474 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1475 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1477 " gl_FragColor = vec4(color);\n"
1480 "#endif // FRAGMENT_SHADER\n"
1483 void R_SetupView(const matrix4x4_t *matrix)
1485 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1486 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1488 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1490 GL_SetupView_Orientation_FromEntity(matrix);
1493 void R_RenderScene(void);
1495 void R_Bloom_StartFrame(void)
1497 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
1499 // set bloomwidth and bloomheight to the bloom resolution that will be
1500 // used (often less than the screen resolution for faster rendering)
1501 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1502 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
1503 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
1505 // calculate desired texture sizes
1506 if (gl_support_arb_texture_non_power_of_two)
1508 screentexturewidth = r_view.width;
1509 screentextureheight = r_view.height;
1510 bloomtexturewidth = r_bloomstate.bloomwidth;
1511 bloomtextureheight = r_bloomstate.bloomheight;
1515 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
1516 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
1517 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
1518 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
1523 screentexturewidth = screentextureheight = 0;
1525 else if (r_bloom.integer)
1530 screentexturewidth = screentextureheight = 0;
1531 bloomtexturewidth = bloomtextureheight = 0;
1534 if ((!bloomtexturewidth && !bloomtextureheight) || r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512 || screentexturewidth > gl_max_texture_size || screentextureheight > gl_max_texture_size || bloomtexturewidth > gl_max_texture_size || bloomtextureheight > gl_max_texture_size)
1536 // can't use bloom if the parameters are too weird
1537 // can't use bloom if the card does not support the texture size
1538 if (r_bloomstate.texture_screen)
1539 R_FreeTexture(r_bloomstate.texture_screen);
1540 if (r_bloomstate.texture_bloom)
1541 R_FreeTexture(r_bloomstate.texture_bloom);
1542 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1546 r_bloomstate.enabled = true;
1547 r_bloomstate.hdr = r_hdr.integer != 0;
1549 // allocate textures as needed
1550 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
1552 if (r_bloomstate.texture_screen)
1553 R_FreeTexture(r_bloomstate.texture_screen);
1554 r_bloomstate.texture_screen = NULL;
1555 r_bloomstate.screentexturewidth = screentexturewidth;
1556 r_bloomstate.screentextureheight = screentextureheight;
1557 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
1558 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1560 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
1562 if (r_bloomstate.texture_bloom)
1563 R_FreeTexture(r_bloomstate.texture_bloom);
1564 r_bloomstate.texture_bloom = NULL;
1565 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
1566 r_bloomstate.bloomtextureheight = bloomtextureheight;
1567 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
1568 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
1571 // vertex coordinates for a quad that covers the screen exactly
1572 r_bloomstate.vertex3f[0] = 0;r_bloomstate.vertex3f[1] = 0;r_bloomstate.vertex3f[2] = 0;
1573 r_bloomstate.vertex3f[3] = 1;r_bloomstate.vertex3f[4] = 0;r_bloomstate.vertex3f[5] = 0;
1574 r_bloomstate.vertex3f[6] = 1;r_bloomstate.vertex3f[7] = 1;r_bloomstate.vertex3f[8] = 0;
1575 r_bloomstate.vertex3f[9] = 0;r_bloomstate.vertex3f[10] = 1;r_bloomstate.vertex3f[11] = 0;
1577 // set up a texcoord array for the full resolution screen image
1578 // (we have to keep this around to copy back during final render)
1579 r_bloomstate.screentexcoord2f[0] = 0;
1580 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1581 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1582 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1583 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1584 r_bloomstate.screentexcoord2f[5] = 0;
1585 r_bloomstate.screentexcoord2f[6] = 0;
1586 r_bloomstate.screentexcoord2f[7] = 0;
1588 // set up a texcoord array for the reduced resolution bloom image
1589 // (which will be additive blended over the screen image)
1590 r_bloomstate.bloomtexcoord2f[0] = 0;
1591 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1592 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1593 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1594 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1595 r_bloomstate.bloomtexcoord2f[5] = 0;
1596 r_bloomstate.bloomtexcoord2f[6] = 0;
1597 r_bloomstate.bloomtexcoord2f[7] = 0;
1600 void R_Bloom_CopyScreenTexture(float colorscale)
1602 r_refdef.stats.bloom++;
1604 R_ResetViewRendering();
1605 R_Mesh_VertexPointer(r_bloomstate.vertex3f);
1606 R_Mesh_ColorPointer(NULL);
1607 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1608 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1610 // copy view into the screen texture
1611 GL_ActiveTexture(0);
1613 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1614 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1616 // now scale it down to the bloom texture size
1618 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1619 GL_BlendFunc(GL_ONE, GL_ZERO);
1620 GL_Color(colorscale, colorscale, colorscale, 1);
1621 // TODO: optimize with multitexture or GLSL
1622 R_Mesh_Draw(0, 4, 2, polygonelements);
1623 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1625 // we now have a bloom image in the framebuffer
1626 // copy it into the bloom image texture for later processing
1627 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1628 GL_ActiveTexture(0);
1630 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1631 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1634 void R_Bloom_CopyHDRTexture(void)
1636 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1637 GL_ActiveTexture(0);
1639 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1640 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1643 void R_Bloom_MakeTexture(void)
1646 float xoffset, yoffset, r;
1648 r_refdef.stats.bloom++;
1650 R_ResetViewRendering();
1651 R_Mesh_VertexPointer(r_bloomstate.vertex3f);
1652 R_Mesh_ColorPointer(NULL);
1654 // we have a bloom image in the framebuffer
1656 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1658 for (x = 1;x < r_bloom_colorexponent.value;)
1661 r = bound(0, r_bloom_colorexponent.value / x, 1);
1662 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1663 GL_Color(r, r, r, 1);
1664 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1665 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1666 R_Mesh_Draw(0, 4, 2, polygonelements);
1667 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1669 // copy the vertically blurred bloom view to a texture
1670 GL_ActiveTexture(0);
1672 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1673 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1676 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
1677 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1678 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f);
1680 for (dir = 0;dir < 2;dir++)
1682 // blend on at multiple vertical offsets to achieve a vertical blur
1683 // TODO: do offset blends using GLSL
1684 GL_BlendFunc(GL_ONE, GL_ZERO);
1685 for (x = -range;x <= range;x++)
1687 if (!dir){xoffset = 0;yoffset = x;}
1688 else {xoffset = x;yoffset = 0;}
1689 xoffset /= (float)r_bloomstate.bloomtexturewidth;
1690 yoffset /= (float)r_bloomstate.bloomtextureheight;
1691 // compute a texcoord array with the specified x and y offset
1692 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
1693 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1694 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1695 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1696 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1697 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
1698 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
1699 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
1700 // this r value looks like a 'dot' particle, fading sharply to
1701 // black at the edges
1702 // (probably not realistic but looks good enough)
1703 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
1704 //r = (dir ? 1.0f : r_bloom_brighten.value)/(range*2+1);
1705 r = (dir ? 1.0f : r_bloom_brighten.value)/(range*2+1)*(1 - x*x/(float)(range*range));
1706 GL_Color(r, r, r, 1);
1707 R_Mesh_Draw(0, 4, 2, polygonelements);
1708 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1709 GL_BlendFunc(GL_ONE, GL_ONE);
1712 // copy the vertically blurred bloom view to a texture
1713 GL_ActiveTexture(0);
1715 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1716 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1719 // apply subtract last
1720 // (just like it would be in a GLSL shader)
1721 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
1723 GL_BlendFunc(GL_ONE, GL_ZERO);
1724 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1725 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1726 GL_Color(1, 1, 1, 1);
1727 R_Mesh_Draw(0, 4, 2, polygonelements);
1728 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1730 GL_BlendFunc(GL_ONE, GL_ONE);
1731 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
1732 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1733 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1734 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
1735 R_Mesh_Draw(0, 4, 2, polygonelements);
1736 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1737 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
1739 // copy the darkened bloom view to a texture
1740 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1741 GL_ActiveTexture(0);
1743 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1744 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1748 void R_HDR_RenderBloomTexture(void)
1750 int oldwidth, oldheight;
1752 oldwidth = r_view.width;
1753 oldheight = r_view.height;
1754 r_view.width = r_bloomstate.bloomwidth;
1755 r_view.height = r_bloomstate.bloomheight;
1757 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
1758 // TODO: add exposure compensation features
1760 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
1763 R_ResetViewRendering();
1765 R_Bloom_CopyHDRTexture();
1766 R_Bloom_MakeTexture();
1768 R_ResetViewRendering();
1769 GL_ScissorTest(true);
1773 if (r_timereport_active)
1774 R_TimeReport("clear");
1776 // restore the view settings
1777 r_view.width = oldwidth;
1778 r_view.height = oldheight;
1781 static void R_BlendView(void)
1783 if (r_bloomstate.enabled && r_bloomstate.hdr)
1785 // render high dynamic range bloom effect
1786 // the bloom texture was made earlier this render, so we just need to
1787 // blend it onto the screen...
1788 R_ResetViewRendering();
1789 R_Mesh_VertexPointer(r_bloomstate.vertex3f);
1790 R_Mesh_ColorPointer(NULL);
1791 GL_Color(1, 1, 1, 1);
1792 GL_BlendFunc(GL_ONE, GL_ONE);
1793 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1794 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1795 R_Mesh_Draw(0, 4, 2, polygonelements);
1796 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1798 else if (r_bloomstate.enabled)
1800 // render simple bloom effect
1801 // copy the screen and shrink it and darken it for the bloom process
1802 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
1803 // make the bloom texture
1804 R_Bloom_MakeTexture();
1805 // put the original screen image back in place and blend the bloom
1807 R_ResetViewRendering();
1808 R_Mesh_VertexPointer(r_bloomstate.vertex3f);
1809 R_Mesh_ColorPointer(NULL);
1810 GL_Color(1, 1, 1, 1);
1811 GL_BlendFunc(GL_ONE, GL_ZERO);
1812 // do both in one pass if possible
1813 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1814 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1815 if (r_textureunits.integer >= 2 && gl_combine.integer)
1817 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1818 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
1819 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f);
1823 R_Mesh_Draw(0, 4, 2, polygonelements);
1824 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1825 // now blend on the bloom texture
1826 GL_BlendFunc(GL_ONE, GL_ONE);
1827 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1828 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1830 R_Mesh_Draw(0, 4, 2, polygonelements);
1831 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1833 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
1835 // apply a color tint to the whole view
1836 R_ResetViewRendering();
1837 R_Mesh_VertexPointer(r_bloomstate.vertex3f);
1838 R_Mesh_ColorPointer(NULL);
1839 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1840 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1841 R_Mesh_Draw(0, 4, 2, polygonelements);
1845 void R_RenderScene(void);
1847 matrix4x4_t r_waterscrollmatrix;
1849 void R_UpdateVariables(void)
1853 r_refdef.farclip = 4096;
1854 if (r_refdef.worldmodel)
1855 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1856 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
1858 r_refdef.polygonfactor = 0;
1859 r_refdef.polygonoffset = 0;
1860 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
1861 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
1863 r_refdef.rtworld = r_shadow_realtime_world.integer;
1864 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1865 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1866 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1867 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1868 if (r_showsurfaces.integer)
1870 r_refdef.rtworld = false;
1871 r_refdef.rtworldshadows = false;
1872 r_refdef.rtdlight = false;
1873 r_refdef.rtdlightshadows = false;
1874 r_refdef.lightmapintensity = 0;
1877 if (gamemode == GAME_NEHAHRA)
1879 if (gl_fogenable.integer)
1881 r_refdef.oldgl_fogenable = true;
1882 r_refdef.fog_density = gl_fogdensity.value;
1883 r_refdef.fog_red = gl_fogred.value;
1884 r_refdef.fog_green = gl_foggreen.value;
1885 r_refdef.fog_blue = gl_fogblue.value;
1887 else if (r_refdef.oldgl_fogenable)
1889 r_refdef.oldgl_fogenable = false;
1890 r_refdef.fog_density = 0;
1891 r_refdef.fog_red = 0;
1892 r_refdef.fog_green = 0;
1893 r_refdef.fog_blue = 0;
1896 if (r_refdef.fog_density)
1898 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
1899 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
1900 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
1902 if (r_refdef.fog_density)
1904 r_refdef.fogenabled = true;
1905 // this is the point where the fog reaches 0.9986 alpha, which we
1906 // consider a good enough cutoff point for the texture
1907 // (0.9986 * 256 == 255.6)
1908 r_refdef.fogrange = 400 / r_refdef.fog_density;
1909 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
1910 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
1911 // fog color was already set
1914 r_refdef.fogenabled = false;
1922 void R_RenderView(void)
1924 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1925 return; //Host_Error ("R_RenderView: NULL worldmodel");
1928 if (r_timereport_active)
1929 R_TimeReport("setup");
1932 if (r_timereport_active)
1933 R_TimeReport("visibility");
1935 R_ResetViewRendering();
1936 GL_ScissorTest(true);
1940 if (r_timereport_active)
1941 R_TimeReport("clear");
1943 R_Bloom_StartFrame();
1945 // this produces a bloom texture to be used in R_BlendView() later
1947 R_HDR_RenderBloomTexture();
1949 r_view.colorscale = r_hdr_scenebrightness.value;
1953 if (r_timereport_active)
1954 R_TimeReport("blendview");
1956 GL_Scissor(0, 0, vid.width, vid.height);
1957 GL_ScissorTest(false);
1961 extern void R_DrawLightningBeams (void);
1962 extern void VM_AddPolygonsToMeshQueue (void);
1963 extern void R_DrawPortals (void);
1964 void R_RenderScene(void)
1968 // don't let sound skip if going slow
1969 if (r_refdef.extraupdate)
1973 if (gl_support_fragment_shader)
1975 qglUseProgramObjectARB(0);CHECKGLERROR
1977 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1978 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1979 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1981 R_ResetViewRendering();
1982 R_SetupView(&r_view.matrix);
1984 R_MeshQueue_BeginScene();
1986 R_Shadow_UpdateWorldLightSelection();
1990 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);
1992 if (cl.csqc_vidvars.drawworld)
1994 // don't let sound skip if going slow
1995 if (r_refdef.extraupdate)
1998 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2000 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2001 if (r_timereport_active)
2002 R_TimeReport("worldsky");
2005 if (R_DrawBrushModelsSky() && r_timereport_active)
2006 R_TimeReport("bmodelsky");
2008 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2010 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2011 if (r_timereport_active)
2012 R_TimeReport("world");
2016 // don't let sound skip if going slow
2017 if (r_refdef.extraupdate)
2021 if (r_timereport_active)
2022 R_TimeReport("models");
2024 // don't let sound skip if going slow
2025 if (r_refdef.extraupdate)
2028 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2030 R_DrawModelShadows();
2032 // don't let sound skip if going slow
2033 if (r_refdef.extraupdate)
2037 R_ShadowVolumeLighting(false);
2038 if (r_timereport_active)
2039 R_TimeReport("rtlights");
2041 // don't let sound skip if going slow
2042 if (r_refdef.extraupdate)
2045 if (cl.csqc_vidvars.drawworld)
2047 R_DrawLightningBeams();
2048 if (r_timereport_active)
2049 R_TimeReport("lightning");
2052 if (r_timereport_active)
2053 R_TimeReport("particles");
2056 if (r_timereport_active)
2057 R_TimeReport("explosions");
2060 if (gl_support_fragment_shader)
2062 qglUseProgramObjectARB(0);CHECKGLERROR
2064 VM_AddPolygonsToMeshQueue();
2066 if (r_drawportals.integer)
2069 if (r_timereport_active)
2070 R_TimeReport("portals");
2073 if (gl_support_fragment_shader)
2075 qglUseProgramObjectARB(0);CHECKGLERROR
2077 R_MeshQueue_RenderTransparent();
2078 if (r_timereport_active)
2079 R_TimeReport("drawtrans");
2081 if (gl_support_fragment_shader)
2083 qglUseProgramObjectARB(0);CHECKGLERROR
2086 if (cl.csqc_vidvars.drawworld)
2089 if (r_timereport_active)
2090 R_TimeReport("coronas");
2093 // don't let sound skip if going slow
2094 if (r_refdef.extraupdate)
2098 if (gl_support_fragment_shader)
2100 qglUseProgramObjectARB(0);CHECKGLERROR
2102 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
2103 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2107 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2110 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2111 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2112 GL_DepthMask(false);
2114 R_Mesh_Matrix(&identitymatrix);
2116 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2117 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2118 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2119 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2120 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2121 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2122 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2123 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2124 R_FillColors(color, 8, cr, cg, cb, ca);
2125 if (r_refdef.fogenabled)
2127 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2129 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
2131 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2132 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2133 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2136 R_Mesh_VertexPointer(vertex3f);
2137 R_Mesh_ColorPointer(color);
2138 R_Mesh_ResetTextureState();
2143 int nomodelelements[24] =
2155 float nomodelvertex3f[6*3] =
2165 float nomodelcolor4f[6*4] =
2167 0.0f, 0.0f, 0.5f, 1.0f,
2168 0.0f, 0.0f, 0.5f, 1.0f,
2169 0.0f, 0.5f, 0.0f, 1.0f,
2170 0.0f, 0.5f, 0.0f, 1.0f,
2171 0.5f, 0.0f, 0.0f, 1.0f,
2172 0.5f, 0.0f, 0.0f, 1.0f
2175 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2180 // this is only called once per entity so numsurfaces is always 1, and
2181 // surfacelist is always {0}, so this code does not handle batches
2182 R_Mesh_Matrix(&ent->matrix);
2184 if (ent->flags & EF_ADDITIVE)
2186 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2187 GL_DepthMask(false);
2189 else if (ent->alpha < 1)
2191 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2192 GL_DepthMask(false);
2196 GL_BlendFunc(GL_ONE, GL_ZERO);
2199 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2200 R_Mesh_VertexPointer(nomodelvertex3f);
2201 if (r_refdef.fogenabled)
2204 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2205 R_Mesh_ColorPointer(color4f);
2206 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2207 f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin));
2209 for (i = 0, c = color4f;i < 6;i++, c += 4)
2211 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2212 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2213 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2217 else if (ent->alpha != 1)
2219 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2220 R_Mesh_ColorPointer(color4f);
2221 for (i = 0, c = color4f;i < 6;i++, c += 4)
2225 R_Mesh_ColorPointer(nomodelcolor4f);
2226 R_Mesh_ResetTextureState();
2227 R_Mesh_Draw(0, 6, 8, nomodelelements);
2230 void R_DrawNoModel(entity_render_t *ent)
2233 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2234 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2235 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2237 // R_DrawNoModelCallback(ent, 0);
2240 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2242 vec3_t right1, right2, diff, normal;
2244 VectorSubtract (org2, org1, normal);
2246 // calculate 'right' vector for start
2247 VectorSubtract (r_view.origin, org1, diff);
2248 CrossProduct (normal, diff, right1);
2249 VectorNormalize (right1);
2251 // calculate 'right' vector for end
2252 VectorSubtract (r_view.origin, org2, diff);
2253 CrossProduct (normal, diff, right2);
2254 VectorNormalize (right2);
2256 vert[ 0] = org1[0] + width * right1[0];
2257 vert[ 1] = org1[1] + width * right1[1];
2258 vert[ 2] = org1[2] + width * right1[2];
2259 vert[ 3] = org1[0] - width * right1[0];
2260 vert[ 4] = org1[1] - width * right1[1];
2261 vert[ 5] = org1[2] - width * right1[2];
2262 vert[ 6] = org2[0] - width * right2[0];
2263 vert[ 7] = org2[1] - width * right2[1];
2264 vert[ 8] = org2[2] - width * right2[2];
2265 vert[ 9] = org2[0] + width * right2[0];
2266 vert[10] = org2[1] + width * right2[1];
2267 vert[11] = org2[2] + width * right2[2];
2270 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2272 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)
2274 float fog = 0.0f, ifog;
2277 if (r_refdef.fogenabled)
2278 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2281 R_Mesh_Matrix(&identitymatrix);
2282 GL_BlendFunc(blendfunc1, blendfunc2);
2283 GL_DepthMask(false);
2284 GL_DepthTest(!depthdisable);
2286 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2287 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2288 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2289 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2290 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2291 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2292 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2293 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2294 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2295 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2296 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2297 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2299 R_Mesh_VertexPointer(vertex3f);
2300 R_Mesh_ColorPointer(NULL);
2301 R_Mesh_ResetTextureState();
2302 R_Mesh_TexBind(0, R_GetTexture(texture));
2303 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2304 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2305 GL_Color(cr * ifog * r_view.colorscale, cg * ifog * r_view.colorscale, cb * ifog * r_view.colorscale, ca);
2306 R_Mesh_Draw(0, 4, 2, polygonelements);
2308 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2310 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2311 GL_BlendFunc(blendfunc1, GL_ONE);
2312 GL_Color(r_refdef.fogcolor[0] * fog * r_view.colorscale, r_refdef.fogcolor[1] * fog * r_view.colorscale, r_refdef.fogcolor[2] * fog * r_view.colorscale, ca);
2313 R_Mesh_Draw(0, 4, 2, polygonelements);
2317 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2322 VectorSet(v, x, y, z);
2323 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2324 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2326 if (i == mesh->numvertices)
2328 if (mesh->numvertices < mesh->maxvertices)
2330 VectorCopy(v, vertex3f);
2331 mesh->numvertices++;
2333 return mesh->numvertices;
2339 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2343 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2344 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2345 e = mesh->element3i + mesh->numtriangles * 3;
2346 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2348 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2349 if (mesh->numtriangles < mesh->maxtriangles)
2354 mesh->numtriangles++;
2356 element[1] = element[2];
2360 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2364 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2365 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2366 e = mesh->element3i + mesh->numtriangles * 3;
2367 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2369 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2370 if (mesh->numtriangles < mesh->maxtriangles)
2375 mesh->numtriangles++;
2377 element[1] = element[2];
2381 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
2382 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2384 int planenum, planenum2;
2387 mplane_t *plane, *plane2;
2389 double temppoints[2][256*3];
2390 // figure out how large a bounding box we need to properly compute this brush
2392 for (w = 0;w < numplanes;w++)
2393 maxdist = max(maxdist, planes[w].dist);
2394 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
2395 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
2396 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2400 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
2401 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2403 if (planenum2 == planenum)
2405 PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
2408 if (tempnumpoints < 3)
2410 // generate elements forming a triangle fan for this polygon
2411 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
2415 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2418 R_Mesh_VertexPointer(brush->points->v);
2419 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2420 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, 0.2f);
2421 GL_LockArrays(0, brush->numpoints);
2422 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2423 GL_LockArrays(0, 0);
2426 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2429 if (!surface->num_collisiontriangles)
2431 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2432 i = (int)(((size_t)surface) / sizeof(msurface_t));
2433 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, 0.2f);
2434 GL_LockArrays(0, surface->num_collisionvertices);
2435 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2436 GL_LockArrays(0, 0);
2439 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)
2441 texturelayer_t *layer;
2442 layer = t->currentlayers + t->currentnumlayers++;
2444 layer->depthmask = depthmask;
2445 layer->blendfunc1 = blendfunc1;
2446 layer->blendfunc2 = blendfunc2;
2447 layer->texture = texture;
2448 layer->texmatrix = *matrix;
2449 layer->color[0] = r * r_view.colorscale;
2450 layer->color[1] = g * r_view.colorscale;
2451 layer->color[2] = b * r_view.colorscale;
2452 layer->color[3] = a;
2455 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2457 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2458 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2460 // switch to an alternate material if this is a q1bsp animated material
2462 texture_t *texture = t;
2463 model_t *model = ent->model;
2464 int s = ent->skinnum;
2465 if ((unsigned int)s >= (unsigned int)model->numskins)
2467 if (model->skinscenes)
2469 if (model->skinscenes[s].framecount > 1)
2470 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2472 s = model->skinscenes[s].firstframe;
2475 t = t + s * model->num_surfaces;
2478 // use an alternate animation if the entity's frame is not 0,
2479 // and only if the texture has an alternate animation
2480 if (ent->frame != 0 && t->anim_total[1])
2481 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2483 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2485 texture->currentframe = t;
2488 // pick a new currentskinframe if the material is animated
2489 if (t->numskinframes >= 2)
2490 t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
2492 t->currentmaterialflags = t->basematerialflags;
2493 t->currentalpha = ent->alpha;
2494 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2495 t->currentalpha *= r_wateralpha.value;
2496 if (!(ent->flags & RENDER_LIGHT))
2497 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2498 if (ent->effects & EF_ADDITIVE)
2499 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2500 else if (t->currentalpha < 1)
2501 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2502 if (ent->effects & EF_NODEPTHTEST)
2503 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2504 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2505 t->currenttexmatrix = r_waterscrollmatrix;
2507 t->currenttexmatrix = identitymatrix;
2509 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2510 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2511 t->glosstexture = r_texture_white;
2512 t->specularpower = r_shadow_glossexponent.value;
2513 t->specularscale = 0;
2514 if (r_shadow_gloss.integer > 0)
2516 if (t->currentskinframe->gloss)
2518 if (r_shadow_glossintensity.value > 0)
2520 t->glosstexture = t->currentskinframe->gloss;
2521 t->specularscale = r_shadow_glossintensity.value;
2524 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2525 t->specularscale = r_shadow_gloss2intensity.value;
2528 t->currentnumlayers = 0;
2529 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2531 if (gl_lightmaps.integer)
2532 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2533 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2535 int blendfunc1, blendfunc2, depthmask;
2536 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2538 blendfunc1 = GL_SRC_ALPHA;
2539 blendfunc2 = GL_ONE;
2541 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2543 blendfunc1 = GL_SRC_ALPHA;
2544 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2546 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2548 blendfunc1 = t->customblendfunc[0];
2549 blendfunc2 = t->customblendfunc[1];
2553 blendfunc1 = GL_ONE;
2554 blendfunc2 = GL_ZERO;
2556 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2557 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2559 rtexture_t *currentbasetexture;
2561 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2562 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2563 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2564 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2566 // fullbright is not affected by r_refdef.lightmapintensity
2567 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2568 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2569 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->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);
2570 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2571 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->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);
2577 // q3bsp has no lightmap updates, so the lightstylevalue that
2578 // would normally be baked into the lightmap must be
2579 // applied to the color
2580 if (ent->model->type == mod_brushq3)
2581 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2582 colorscale *= r_refdef.lightmapintensity;
2583 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
2584 if (r_ambient.value >= (1.0f/64.0f))
2585 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);
2586 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2588 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->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);
2589 if (r_ambient.value >= (1.0f/64.0f))
2590 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->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);
2592 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2594 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->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);
2595 if (r_ambient.value >= (1.0f/64.0f))
2596 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->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);
2599 if (t->currentskinframe->glow != NULL)
2600 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->currentalpha);
2601 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2603 // if this is opaque use alpha blend which will darken the earlier
2606 // if this is an alpha blended material, all the earlier passes
2607 // were darkened by fog already, so we only need to add the fog
2608 // color ontop through the fog mask texture
2610 // if this is an additive blended material, all the earlier passes
2611 // were darkened by fog already, and we should not add fog color
2612 // (because the background was not darkened, there is no fog color
2613 // that was lost behind it).
2614 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
2621 void R_UpdateAllTextureInfo(entity_render_t *ent)
2625 for (i = 0;i < ent->model->num_textures;i++)
2626 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2629 int rsurface_array_size = 0;
2630 float *rsurface_array_modelvertex3f = NULL;
2631 float *rsurface_array_modelsvector3f = NULL;
2632 float *rsurface_array_modeltvector3f = NULL;
2633 float *rsurface_array_modelnormal3f = NULL;
2634 float *rsurface_array_deformedvertex3f = NULL;
2635 float *rsurface_array_deformedsvector3f = NULL;
2636 float *rsurface_array_deformedtvector3f = NULL;
2637 float *rsurface_array_deformednormal3f = NULL;
2638 float *rsurface_array_color4f = NULL;
2639 float *rsurface_array_texcoord3f = NULL;
2641 void R_Mesh_ResizeArrays(int newvertices)
2644 if (rsurface_array_size >= newvertices)
2646 if (rsurface_array_modelvertex3f)
2647 Mem_Free(rsurface_array_modelvertex3f);
2648 rsurface_array_size = (newvertices + 1023) & ~1023;
2649 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2650 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2651 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2652 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2653 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2654 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2655 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2656 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2657 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2658 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2659 rsurface_array_color4f = base + rsurface_array_size * 27;
2662 float *rsurface_modelvertex3f;
2663 float *rsurface_modelsvector3f;
2664 float *rsurface_modeltvector3f;
2665 float *rsurface_modelnormal3f;
2666 float *rsurface_vertex3f;
2667 float *rsurface_svector3f;
2668 float *rsurface_tvector3f;
2669 float *rsurface_normal3f;
2670 float *rsurface_lightmapcolor4f;
2671 vec3_t rsurface_modelorg;
2672 qboolean rsurface_generatedvertex;
2673 const entity_render_t *rsurface_entity;
2674 const model_t *rsurface_model;
2675 texture_t *rsurface_texture;
2676 rtexture_t *rsurface_lightmaptexture;
2677 rsurfmode_t rsurface_mode;
2678 texture_t *rsurface_glsl_texture;
2679 qboolean rsurface_glsl_uselightmap;
2681 void RSurf_CleanUp(void)
2684 if (rsurface_mode == RSURFMODE_GLSL)
2686 qglUseProgramObjectARB(0);CHECKGLERROR
2688 GL_AlphaTest(false);
2689 rsurface_mode = RSURFMODE_NONE;
2690 rsurface_lightmaptexture = NULL;
2691 rsurface_texture = NULL;
2692 rsurface_glsl_texture = NULL;
2693 rsurface_glsl_uselightmap = false;
2696 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2699 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2700 rsurface_entity = ent;
2701 rsurface_model = ent->model;
2702 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2703 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2704 R_Mesh_Matrix(&ent->matrix);
2705 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2706 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
2710 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2711 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2712 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2713 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2714 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2716 else if (wantnormals)
2718 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2719 rsurface_modelsvector3f = NULL;
2720 rsurface_modeltvector3f = NULL;
2721 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2722 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2726 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2727 rsurface_modelsvector3f = NULL;
2728 rsurface_modeltvector3f = NULL;
2729 rsurface_modelnormal3f = NULL;
2730 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2732 rsurface_generatedvertex = true;
2736 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2737 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2738 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2739 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2740 rsurface_generatedvertex = false;
2742 rsurface_vertex3f = rsurface_modelvertex3f;
2743 rsurface_svector3f = rsurface_modelsvector3f;
2744 rsurface_tvector3f = rsurface_modeltvector3f;
2745 rsurface_normal3f = rsurface_modelnormal3f;
2748 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2750 // if vertices are dynamic (animated models), generate them into the temporary rsurface_array_model* arrays and point rsurface_model* at them instead of the static data from the model itself
2751 if (rsurface_generatedvertex)
2753 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2754 generatetangents = true;
2755 if (generatetangents)
2756 generatenormals = true;
2757 if (generatenormals && !rsurface_modelnormal3f)
2759 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2760 Mod_BuildNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_element3i, rsurface_array_modelnormal3f, r_smoothnormals_areaweighting.integer);
2762 if (generatetangents && !rsurface_modelsvector3f)
2764 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2765 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2766 Mod_BuildTextureVectorsFromNormals(0, rsurface_model->surfmesh.num_vertices, rsurface_model->surfmesh.num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_modelnormal3f, rsurface_model->surfmesh.data_element3i, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f, r_smoothnormals_areaweighting.integer);
2769 // if vertices are deformed (sprite flares and things in maps, possibly water waves, bulges and other deformations), generate them into rsurface_deform* arrays from whatever the rsurface_model* array pointers point to (may be static model data or generated data for an animated model)
2770 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2772 int texturesurfaceindex;
2773 float center[3], forward[3], right[3], up[3], v[4][3];
2774 matrix4x4_t matrix1, imatrix1;
2775 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2776 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2777 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2778 // make deformed versions of only the model vertices used by the specified surfaces
2779 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2782 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2783 // a single autosprite surface can contain multiple sprites...
2784 for (j = 0;j < surface->num_vertices - 3;j += 4)
2786 VectorClear(center);
2787 for (i = 0;i < 4;i++)
2788 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2789 VectorScale(center, 0.25f, center);
2790 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2792 forward[0] = rsurface_modelorg[0] - center[0];
2793 forward[1] = rsurface_modelorg[1] - center[1];
2795 VectorNormalize(forward);
2796 right[0] = forward[1];
2797 right[1] = -forward[0];
2799 VectorSet(up, 0, 0, 1);
2801 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2802 Matrix4x4_FromVectors(&matrix1, (rsurface_modelnormal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_modelsvector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_modeltvector3f + 3 * surface->num_firstvertex) + j*3, center);
2803 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2804 for (i = 0;i < 4;i++)
2805 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2806 for (i = 0;i < 4;i++)
2807 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
2809 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_deformednormal3f, r_smoothnormals_areaweighting.integer);
2810 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_modelvertex3f, rsurface_model->surfmesh.data_texcoordtexture2f, rsurface_array_deformednormal3f, rsurface_model->surfmesh.data_element3i + surface->num_firsttriangle * 3, rsurface_array_deformedsvector3f, rsurface_array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
2812 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2813 rsurface_svector3f = rsurface_array_deformedsvector3f;
2814 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2815 rsurface_normal3f = rsurface_array_deformednormal3f;
2819 rsurface_vertex3f = rsurface_modelvertex3f;
2820 rsurface_svector3f = rsurface_modelsvector3f;
2821 rsurface_tvector3f = rsurface_modeltvector3f;
2822 rsurface_normal3f = rsurface_modelnormal3f;
2824 R_Mesh_VertexPointer(rsurface_vertex3f);
2827 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2829 int texturesurfaceindex;
2830 const msurface_t *surface = texturesurfacelist[0];
2831 int firstvertex = surface->num_firstvertex;
2832 int endvertex = surface->num_firstvertex + surface->num_vertices;
2833 if (texturenumsurfaces == 1)
2835 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2836 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2838 else if (r_batchmode.integer == 2)
2840 #define MAXBATCHTRIANGLES 4096
2841 int batchtriangles = 0;
2842 int batchelements[MAXBATCHTRIANGLES*3];
2843 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2845 surface = texturesurfacelist[texturesurfaceindex];
2846 if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2848 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2851 if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2853 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2855 firstvertex = surface->num_firstvertex;
2856 endvertex = surface->num_firstvertex + surface->num_vertices;
2860 firstvertex = min(firstvertex, surface->num_firstvertex);
2861 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2863 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2864 batchtriangles += surface->num_triangles;
2867 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2869 else if (r_batchmode.integer == 1)
2871 int firsttriangle = 0;
2872 int endtriangle = -1;
2873 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2875 surface = texturesurfacelist[texturesurfaceindex];
2876 if (surface->num_firsttriangle != endtriangle)
2878 if (endtriangle > firsttriangle)
2880 GL_LockArrays(firstvertex, endvertex - firstvertex);
2881 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2883 firstvertex = surface->num_firstvertex;
2884 endvertex = surface->num_firstvertex + surface->num_vertices;
2885 firsttriangle = surface->num_firsttriangle;
2889 firstvertex = min(firstvertex, surface->num_firstvertex);
2890 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2892 endtriangle = surface->num_firsttriangle + surface->num_triangles;
2894 if (endtriangle > firsttriangle)
2896 GL_LockArrays(firstvertex, endvertex - firstvertex);
2897 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2902 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2904 surface = texturesurfacelist[texturesurfaceindex];
2905 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2906 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2911 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2913 int texturesurfaceindex;
2914 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2916 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2917 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2918 GL_Color((k & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_view.colorscale, 0.2f);
2919 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2920 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2924 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2926 int texturesurfaceindex;
2934 vec3_t ambientcolor;
2935 vec3_t diffusecolor;
2937 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2938 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2939 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2940 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2941 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2942 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2943 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2944 if (VectorLength2(diffusecolor) > 0)
2946 // generate color arrays for the surfaces in this list
2947 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2949 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2950 int numverts = surface->num_vertices;
2951 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2952 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2953 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2954 // q3-style directional shading
2955 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2957 if ((f = DotProduct(c2, lightdir)) > 0)
2958 VectorMA(ambientcolor, f, diffusecolor, c);
2960 VectorCopy(ambientcolor, c);
2969 rsurface_lightmapcolor4f = rsurface_array_color4f;
2973 r = ambientcolor[0];
2974 g = ambientcolor[1];
2975 b = ambientcolor[2];
2976 rsurface_lightmapcolor4f = NULL;
2979 else if (lightmode >= 1 || !rsurface_lightmaptexture)
2981 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2983 // generate color arrays for the surfaces in this list
2984 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2986 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2987 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2989 if (surface->lightmapinfo->samples)
2991 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2992 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2993 VectorScale(lm, scale, c);
2994 if (surface->lightmapinfo->styles[1] != 255)
2996 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
2998 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
2999 VectorMA(c, scale, lm, c);
3000 if (surface->lightmapinfo->styles[2] != 255)
3003 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3004 VectorMA(c, scale, lm, c);
3005 if (surface->lightmapinfo->styles[3] != 255)
3008 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3009 VectorMA(c, scale, lm, c);
3019 rsurface_lightmapcolor4f = rsurface_array_color4f;
3022 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3027 rsurface_lightmapcolor4f = NULL;
3031 if (rsurface_lightmapcolor4f)
3033 // generate color arrays for the surfaces in this list
3034 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3036 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3037 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
3039 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3049 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3051 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3052 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
3054 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3062 rsurface_lightmapcolor4f = rsurface_array_color4f;
3064 if (applycolor && rsurface_lightmapcolor4f)
3066 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3068 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3069 for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
3077 rsurface_lightmapcolor4f = rsurface_array_color4f;
3079 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3080 GL_Color(r, g, b, a);
3081 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3084 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3086 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3088 rsurface_mode = RSURFMODE_SHOWSURFACES;
3090 GL_BlendFunc(GL_ONE, GL_ZERO);
3091 R_Mesh_ColorPointer(NULL);
3092 R_Mesh_ResetTextureState();
3094 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3095 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3098 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3100 // transparent sky would be ridiculous
3101 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3103 if (rsurface_mode != RSURFMODE_SKY)
3105 if (rsurface_mode == RSURFMODE_GLSL)
3107 qglUseProgramObjectARB(0);CHECKGLERROR
3109 rsurface_mode = RSURFMODE_SKY;
3113 skyrendernow = false;
3115 // restore entity matrix
3116 R_Mesh_Matrix(&rsurface_entity->matrix);
3119 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3120 // skymasking on them, and Quake3 never did sky masking (unlike
3121 // software Quake and software Quake2), so disable the sky masking
3122 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3123 // and skymasking also looks very bad when noclipping outside the
3124 // level, so don't use it then either.
3125 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3127 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3128 R_Mesh_ColorPointer(NULL);
3129 R_Mesh_ResetTextureState();
3130 if (skyrendermasked)
3132 // depth-only (masking)
3133 GL_ColorMask(0,0,0,0);
3134 // just to make sure that braindead drivers don't draw
3135 // anything despite that colormask...
3136 GL_BlendFunc(GL_ZERO, GL_ONE);
3141 GL_BlendFunc(GL_ONE, GL_ZERO);
3143 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3144 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3145 if (skyrendermasked)
3146 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3150 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3153 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3154 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3155 if (rsurface_mode != RSURFMODE_GLSL)
3157 rsurface_mode = RSURFMODE_GLSL;
3158 rsurface_glsl_texture = NULL;
3159 rsurface_glsl_uselightmap = false;
3160 R_Mesh_ResetTextureState();
3162 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
3164 rsurface_glsl_texture = rsurface_texture;
3165 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
3166 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3167 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3168 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3169 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
3170 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
3171 //if (r_glsl_deluxemapping.integer)
3172 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
3173 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3174 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3175 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3177 if (!r_glsl_permutation)
3179 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
3180 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3181 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3182 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3183 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3185 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3186 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3187 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3188 R_Mesh_ColorPointer(NULL);
3190 else if (rsurface_lightmaptexture)
3192 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
3193 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3194 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3195 R_Mesh_ColorPointer(NULL);
3199 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3200 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3201 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3202 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3204 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3207 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3209 // OpenGL 1.3 path - anything not completely ancient
3210 int texturesurfaceindex;
3212 qboolean applycolor;
3216 const texturelayer_t *layer;
3218 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3219 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3220 if (rsurface_mode != RSURFMODE_MULTIPASS)
3221 rsurface_mode = RSURFMODE_MULTIPASS;
3222 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3223 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3226 int layertexrgbscale;
3227 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3229 if (layerindex == 0)
3233 GL_AlphaTest(false);
3234 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3237 GL_DepthMask(layer->depthmask);
3238 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3239 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3241 layertexrgbscale = 4;
3242 VectorScale(layer->color, 0.25f, layercolor);
3244 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3246 layertexrgbscale = 2;
3247 VectorScale(layer->color, 0.5f, layercolor);
3251 layertexrgbscale = 1;
3252 VectorScale(layer->color, 1.0f, layercolor);
3254 layercolor[3] = layer->color[3];
3255 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3256 R_Mesh_ColorPointer(NULL);
3257 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3258 switch (layer->type)
3260 case TEXTURELAYERTYPE_LITTEXTURE:
3261 memset(&m, 0, sizeof(m));
3262 if (lightmode >= 1 || !rsurface_lightmaptexture)
3263 m.tex[0] = R_GetTexture(r_texture_white);
3265 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3266 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3267 m.tex[1] = R_GetTexture(layer->texture);
3268 m.texmatrix[1] = layer->texmatrix;
3269 m.texrgbscale[1] = layertexrgbscale;
3270 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3271 R_Mesh_TextureState(&m);
3272 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
3274 case TEXTURELAYERTYPE_TEXTURE:
3275 memset(&m, 0, sizeof(m));
3276 m.tex[0] = R_GetTexture(layer->texture);
3277 m.texmatrix[0] = layer->texmatrix;
3278 m.texrgbscale[0] = layertexrgbscale;
3279 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3280 R_Mesh_TextureState(&m);
3281 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3283 case TEXTURELAYERTYPE_FOG:
3284 memset(&m, 0, sizeof(m));
3285 m.texrgbscale[0] = layertexrgbscale;
3288 m.tex[0] = R_GetTexture(layer->texture);
3289 m.texmatrix[0] = layer->texmatrix;
3290 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3292 R_Mesh_TextureState(&m);
3293 // generate a color array for the fog pass
3294 R_Mesh_ColorPointer(rsurface_array_color4f);
3295 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3299 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3300 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
3302 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3303 c[0] = layercolor[0];
3304 c[1] = layercolor[1];
3305 c[2] = layercolor[2];
3306 c[3] = f * layercolor[3];
3309 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3312 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3314 GL_LockArrays(0, 0);
3317 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3319 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3320 GL_AlphaTest(false);
3324 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3326 // OpenGL 1.1 - crusty old voodoo path
3327 int texturesurfaceindex;
3332 const texturelayer_t *layer;
3334 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3335 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3336 if (rsurface_mode != RSURFMODE_MULTIPASS)
3337 rsurface_mode = RSURFMODE_MULTIPASS;
3338 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3339 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3341 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3343 if (layerindex == 0)
3347 GL_AlphaTest(false);
3348 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3351 GL_DepthMask(layer->depthmask);
3352 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3353 R_Mesh_ColorPointer(NULL);
3354 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3355 switch (layer->type)
3357 case TEXTURELAYERTYPE_LITTEXTURE:
3358 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3360 // two-pass lit texture with 2x rgbscale
3361 // first the lightmap pass
3362 memset(&m, 0, sizeof(m));
3363 if (lightmode >= 1 || !rsurface_lightmaptexture)
3364 m.tex[0] = R_GetTexture(r_texture_white);
3366 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3367 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3368 R_Mesh_TextureState(&m);
3369 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3370 GL_LockArrays(0, 0);
3371 // then apply the texture to it
3372 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3373 memset(&m, 0, sizeof(m));
3374 m.tex[0] = R_GetTexture(layer->texture);
3375 m.texmatrix[0] = layer->texmatrix;
3376 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3377 R_Mesh_TextureState(&m);
3378 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], 0, layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
3382 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3383 memset(&m, 0, sizeof(m));
3384 m.tex[0] = R_GetTexture(layer->texture);
3385 m.texmatrix[0] = layer->texmatrix;
3386 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3387 R_Mesh_TextureState(&m);
3388 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], lightmode == 2 ? 2 : 1, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3391 case TEXTURELAYERTYPE_TEXTURE:
3392 // singletexture unlit texture with transparency support
3393 memset(&m, 0, sizeof(m));
3394 m.tex[0] = R_GetTexture(layer->texture);
3395 m.texmatrix[0] = layer->texmatrix;
3396 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3397 R_Mesh_TextureState(&m);
3398 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], 0, layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
3400 case TEXTURELAYERTYPE_FOG:
3401 // singletexture fogging
3402 R_Mesh_ColorPointer(rsurface_array_color4f);
3405 memset(&m, 0, sizeof(m));
3406 m.tex[0] = R_GetTexture(layer->texture);
3407 m.texmatrix[0] = layer->texmatrix;
3408 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3409 R_Mesh_TextureState(&m);
3412 R_Mesh_ResetTextureState();
3413 // generate a color array for the fog pass
3414 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3418 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3419 for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
3421 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3422 c[0] = layer->color[0];
3423 c[1] = layer->color[1];
3424 c[2] = layer->color[2];
3425 c[3] = f * layer->color[3];
3428 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3431 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3433 GL_LockArrays(0, 0);
3436 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3438 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3439 GL_AlphaTest(false);
3443 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3445 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3447 r_shadow_rtlight = NULL;
3448 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3450 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3451 GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3452 if (r_showsurfaces.integer)
3453 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3454 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3455 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3456 else if (rsurface_texture->currentnumlayers)
3458 if (r_glsl.integer && gl_support_fragment_shader)
3459 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3460 else if (gl_combine.integer && r_textureunits.integer >= 2)
3461 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3463 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3466 GL_LockArrays(0, 0);
3469 #define BATCHSIZE 256
3470 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3472 int surfacelistindex;
3475 msurface_t *texturesurfacelist[BATCHSIZE];
3476 // if the model is static it doesn't matter what value we give for
3477 // wantnormals and wanttangents, so this logic uses only rules applicable
3478 // to a model, knowing that they are meaningless otherwise
3479 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3480 RSurf_ActiveEntity(ent, false, false);
3482 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3485 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3487 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3489 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3492 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
3493 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3495 t = surface->texture;
3496 rsurface_lightmaptexture = surface->lightmaptexture;
3497 R_UpdateTextureInfo(ent, t);
3498 rsurface_texture = t->currentframe;
3501 texturesurfacelist[batchcount++] = surface;
3504 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
3505 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3509 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3511 int texturesurfaceindex;
3512 vec3_t tempcenter, center;
3513 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3515 // drawing sky transparently would be too difficult
3516 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3518 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3520 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3521 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3522 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3523 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3524 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3525 R_MeshQueue_AddTransparent(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, rsurface_entity, surface - rsurface_model->data_surfaces, r_shadow_rtlight);
3530 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3533 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3534 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3536 int i, j, f, flagsmask;
3537 int counttriangles = 0;
3539 model_t *model = ent->model;
3540 const int maxsurfacelist = 1024;
3541 int numsurfacelist = 0;
3542 msurface_t *surfacelist[1024];
3546 // if the model is static it doesn't matter what value we give for
3547 // wantnormals and wanttangents, so this logic uses only rules applicable
3548 // to a model, knowing that they are meaningless otherwise
3549 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3550 RSurf_ActiveEntity(ent, false, false);
3552 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3554 // update light styles
3555 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3557 msurface_t *surface, **surfacechain;
3558 for (i = 0;i < model->brushq1.light_styles;i++)
3560 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3562 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3563 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3564 for (;(surface = *surfacechain);surfacechain++)
3565 surface->cached_dlight = true;
3570 R_UpdateAllTextureInfo(ent);
3571 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3574 rsurface_lightmaptexture = NULL;
3575 rsurface_texture = NULL;
3577 if (ent == r_refdef.worldentity)
3579 msurface_t *surface;
3580 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3582 if (!r_viewcache.world_surfacevisible[j])
3584 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3588 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3591 t = surface->texture;
3592 rsurface_lightmaptexture = surface->lightmaptexture;
3593 rsurface_texture = t->currentframe;
3594 f = rsurface_texture->currentmaterialflags & flagsmask;
3596 if (f && surface->num_triangles)
3598 // if lightmap parameters changed, rebuild lightmap texture
3599 if (surface->cached_dlight)
3600 R_BuildLightMap(ent, surface);
3601 // add face to draw list
3602 surfacelist[numsurfacelist++] = surface;
3603 counttriangles += surface->num_triangles;
3604 if (numsurfacelist >= maxsurfacelist)
3606 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3614 msurface_t *surface;
3615 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3617 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3621 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3624 t = surface->texture;
3625 rsurface_lightmaptexture = surface->lightmaptexture;
3626 rsurface_texture = t->currentframe;
3627 f = rsurface_texture->currentmaterialflags & flagsmask;
3629 if (f && surface->num_triangles)
3631 // if lightmap parameters changed, rebuild lightmap texture
3632 if (surface->cached_dlight)
3633 R_BuildLightMap(ent, surface);
3634 // add face to draw list
3635 surfacelist[numsurfacelist++] = surface;
3636 counttriangles += surface->num_triangles;
3637 if (numsurfacelist >= maxsurfacelist)
3639 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3646 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3647 r_refdef.stats.entities_triangles += counttriangles;
3650 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3653 const msurface_t *surface;
3656 R_Mesh_Matrix(&ent->matrix);
3657 R_Mesh_ColorPointer(NULL);
3658 R_Mesh_ResetTextureState();
3659 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3660 GL_DepthMask(false);
3661 GL_DepthTest(!r_showdisabledepthtest.integer);
3662 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3663 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3664 if (brush->colbrushf && brush->colbrushf->numtriangles)
3665 R_DrawCollisionBrush(brush->colbrushf);
3666 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3667 if (surface->num_collisiontriangles)
3668 R_DrawCollisionSurface(ent, surface);
3669 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3672 if (r_showtris.integer || r_shownormals.integer)
3675 msurface_t *surface;
3676 const int *elements;
3681 if (r_showdisabledepthtest.integer)
3683 qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3685 GL_BlendFunc(GL_ONE, GL_ZERO);
3686 R_Mesh_ColorPointer(NULL);
3687 R_Mesh_ResetTextureState();
3688 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3690 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3692 rsurface_texture = surface->texture->currentframe;
3693 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3695 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3696 if (r_showtris.integer)
3698 if (!rsurface_texture->currentlayers->depthmask)
3699 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
3700 else if (ent == r_refdef.worldentity)
3701 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
3703 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
3704 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3707 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3709 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3710 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3711 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3716 if (r_shownormals.integer)
3718 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
3720 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3722 VectorCopy(rsurface_vertex3f + l * 3, v);
3723 qglVertex3f(v[0], v[1], v[2]);
3724 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3725 qglVertex3f(v[0], v[1], v[2]);
3729 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
3731 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3733 VectorCopy(rsurface_vertex3f + l * 3, v);
3734 qglVertex3f(v[0], v[1], v[2]);
3735 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3736 qglVertex3f(v[0], v[1], v[2]);
3740 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
3742 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3744 VectorCopy(rsurface_vertex3f + l * 3, v);
3745 qglVertex3f(v[0], v[1], v[2]);
3746 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3747 qglVertex3f(v[0], v[1], v[2]);
3754 rsurface_texture = NULL;
3755 if (r_showdisabledepthtest.integer)
3757 qglDepthFunc(GL_LEQUAL);CHECKGLERROR