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
122 float screentexcoord2f[8];
123 float bloomtexcoord2f[8];
124 float offsettexcoord2f[8];
128 rtexture_t *r_texture_blanknormalmap;
129 rtexture_t *r_texture_white;
130 rtexture_t *r_texture_black;
131 rtexture_t *r_texture_notexture;
132 rtexture_t *r_texture_whitecube;
133 rtexture_t *r_texture_normalizationcube;
134 rtexture_t *r_texture_fogattenuation;
135 //rtexture_t *r_texture_fogintensity;
137 // information about each possible shader permutation
138 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_COUNT];
139 // currently selected permutation
140 r_glsl_permutation_t *r_glsl_permutation;
142 // temporary variable used by a macro
145 // vertex coordinates for a quad that covers the screen exactly
146 const static float r_screenvertex3f[12] =
154 extern void R_DrawModelShadows(void);
156 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
159 for (i = 0;i < verts;i++)
170 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
173 for (i = 0;i < verts;i++)
183 // FIXME: move this to client?
186 if (gamemode == GAME_NEHAHRA)
188 Cvar_Set("gl_fogenable", "0");
189 Cvar_Set("gl_fogdensity", "0.2");
190 Cvar_Set("gl_fogred", "0.3");
191 Cvar_Set("gl_foggreen", "0.3");
192 Cvar_Set("gl_fogblue", "0.3");
194 r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f;
197 // FIXME: move this to client?
198 void FOG_registercvars(void)
203 if (gamemode == GAME_NEHAHRA)
205 Cvar_RegisterVariable (&gl_fogenable);
206 Cvar_RegisterVariable (&gl_fogdensity);
207 Cvar_RegisterVariable (&gl_fogred);
208 Cvar_RegisterVariable (&gl_foggreen);
209 Cvar_RegisterVariable (&gl_fogblue);
210 Cvar_RegisterVariable (&gl_fogstart);
211 Cvar_RegisterVariable (&gl_fogend);
214 r = (-1.0/256.0) * (FOGTABLEWIDTH * FOGTABLEWIDTH);
215 for (x = 0;x < FOGTABLEWIDTH;x++)
217 alpha = exp(r / ((double)x*(double)x));
218 if (x == FOGTABLEWIDTH - 1)
220 r_refdef.fogtable[x] = bound(0, alpha, 1);
224 static void R_BuildBlankTextures(void)
226 unsigned char data[4];
227 data[0] = 128; // normal X
228 data[1] = 128; // normal Y
229 data[2] = 255; // normal Z
230 data[3] = 128; // height
231 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
236 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
241 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
244 static void R_BuildNoTexture(void)
247 unsigned char pix[16][16][4];
248 // this makes a light grey/dark grey checkerboard texture
249 for (y = 0;y < 16;y++)
251 for (x = 0;x < 16;x++)
253 if ((y < 8) ^ (x < 8))
269 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
272 static void R_BuildWhiteCube(void)
274 unsigned char data[6*1*1*4];
275 data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
276 data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
277 data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
278 data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
279 data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
280 data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
281 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
284 static void R_BuildNormalizationCube(void)
288 vec_t s, t, intensity;
290 unsigned char data[6][NORMSIZE][NORMSIZE][4];
291 for (side = 0;side < 6;side++)
293 for (y = 0;y < NORMSIZE;y++)
295 for (x = 0;x < NORMSIZE;x++)
297 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
298 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
333 intensity = 127.0f / sqrt(DotProduct(v, v));
334 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[0]);
335 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
336 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[2]);
337 data[side][y][x][3] = 255;
341 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
344 static void R_BuildFogTexture(void)
349 unsigned char data1[FOGWIDTH][4];
350 //unsigned char data2[FOGWIDTH][4];
351 r = (-1.0/256.0) * (FOGWIDTH * FOGWIDTH);
352 for (x = 0;x < FOGWIDTH;x++)
354 alpha = exp(r / ((double)x*(double)x));
355 if (x == FOGWIDTH - 1)
357 b = (int)(256.0 * alpha);
358 b = bound(0, b, 255);
359 data1[x][0] = 255 - b;
360 data1[x][1] = 255 - b;
361 data1[x][2] = 255 - b;
368 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
369 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
372 static const char *builtinshaderstring =
373 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
374 "// written by Forest 'LordHavoc' Hale\n"
376 "// common definitions between vertex shader and fragment shader:\n"
378 "#ifdef __GLSL_CG_DATA_TYPES\n"
379 "#define myhalf half\n"
380 "#define myhvec2 hvec2\n"
381 "#define myhvec3 hvec3\n"
382 "#define myhvec4 hvec4\n"
384 "#define myhalf float\n"
385 "#define myhvec2 vec2\n"
386 "#define myhvec3 vec3\n"
387 "#define myhvec4 vec4\n"
390 "varying vec2 TexCoord;\n"
391 "varying vec2 TexCoordLightmap;\n"
393 "varying vec3 CubeVector;\n"
394 "varying vec3 LightVector;\n"
395 "varying vec3 EyeVector;\n"
397 "varying vec3 EyeVectorModelSpace;\n"
400 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
401 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
402 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
407 "// vertex shader specific:\n"
408 "#ifdef VERTEX_SHADER\n"
410 "uniform vec3 LightPosition;\n"
411 "uniform vec3 EyePosition;\n"
412 "uniform vec3 LightDir;\n"
414 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
418 " gl_FrontColor = gl_Color;\n"
419 " // copy the surface texcoord\n"
420 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
421 "#if !defined(MODE_LIGHTSOURCE) && !defined(MODE_LIGHTDIRECTION)\n"
422 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
425 "#ifdef MODE_LIGHTSOURCE\n"
426 " // transform vertex position into light attenuation/cubemap space\n"
427 " // (-1 to +1 across the light box)\n"
428 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
430 " // transform unnormalized light direction into tangent space\n"
431 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
432 " // normalize it per pixel)\n"
433 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
434 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
435 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
436 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
439 "#ifdef MODE_LIGHTDIRECTION\n"
440 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
441 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
442 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
445 " // transform unnormalized eye direction into tangent space\n"
447 " vec3 EyeVectorModelSpace;\n"
449 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
450 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
451 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
452 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
454 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
455 " VectorS = gl_MultiTexCoord1.xyz;\n"
456 " VectorT = gl_MultiTexCoord2.xyz;\n"
457 " VectorR = gl_MultiTexCoord3.xyz;\n"
460 " // transform vertex to camera space, using ftransform to match non-VS\n"
462 " gl_Position = ftransform();\n"
465 "#endif // VERTEX_SHADER\n"
470 "// fragment shader specific:\n"
471 "#ifdef FRAGMENT_SHADER\n"
473 "uniform sampler2D Texture_Normal;\n"
474 "uniform sampler2D Texture_Color;\n"
475 "uniform sampler2D Texture_Gloss;\n"
476 "uniform samplerCube Texture_Cube;\n"
477 "uniform sampler2D Texture_FogMask;\n"
478 "uniform sampler2D Texture_Pants;\n"
479 "uniform sampler2D Texture_Shirt;\n"
480 "uniform sampler2D Texture_Lightmap;\n"
481 "uniform sampler2D Texture_Deluxemap;\n"
482 "uniform sampler2D Texture_Glow;\n"
484 "uniform myhvec3 LightColor;\n"
485 "uniform myhvec3 AmbientColor;\n"
486 "uniform myhvec3 DiffuseColor;\n"
487 "uniform myhvec3 SpecularColor;\n"
488 "uniform myhvec3 Color_Pants;\n"
489 "uniform myhvec3 Color_Shirt;\n"
490 "uniform myhvec3 FogColor;\n"
492 "uniform myhalf GlowScale;\n"
493 "uniform myhalf SceneBrightness;\n"
495 "uniform float OffsetMapping_Scale;\n"
496 "uniform float OffsetMapping_Bias;\n"
497 "uniform float FogRangeRecip;\n"
499 "uniform myhalf AmbientScale;\n"
500 "uniform myhalf DiffuseScale;\n"
501 "uniform myhalf SpecularScale;\n"
502 "uniform myhalf SpecularPower;\n"
506 " // apply offsetmapping\n"
507 "#ifdef USEOFFSETMAPPING\n"
508 " vec2 TexCoordOffset = TexCoord;\n"
509 "#define TexCoord TexCoordOffset\n"
511 " vec3 eyedir = vec3(normalize(EyeVector));\n"
512 " float depthbias = 1.0 - eyedir.z; // should this be a -?\n"
513 " depthbias = 1.0 - depthbias * depthbias;\n"
515 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
516 " // 14 sample relief mapping: linear search and then binary search\n"
517 " //vec3 OffsetVector = vec3(EyeVector.xy * (1.0 / EyeVector.z) * depthbias * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
518 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
519 " vec3 OffsetVector = vec3(eyedir.xy * OffsetMapping_Scale * vec2(-0.1, 0.1), -0.1);\n"
520 " vec3 RT = vec3(TexCoord - OffsetVector.xy * 10.0, 1.0) + OffsetVector;\n"
521 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
522 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
523 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
524 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
525 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
526 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
527 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
528 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;\n"
529 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
530 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
531 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
532 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
533 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
534 " if (RT.z > texture2D(Texture_Normal, RT.xy).a) RT += OffsetVector;OffsetVector *= 0.5;RT -= OffsetVector;\n"
535 " TexCoord = RT.xy;\n"
537 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
538 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
539 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
540 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
541 " //TexCoord += OffsetVector * 3.0;\n"
542 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
543 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
544 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
546 " // 10 sample offset mapping\n"
547 " //vec2 OffsetVector = vec2(EyeVector.xy * (1.0 / EyeVector.z) * depthbias) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
548 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy)) * OffsetMapping_Scale * vec2(-0.333, 0.333);\n"
549 " vec2 OffsetVector = vec2(eyedir.xy) * OffsetMapping_Scale * vec2(-0.1, 0.1);\n"
550 " //TexCoord += OffsetVector * 3.0;\n"
551 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
552 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
553 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
554 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
555 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
556 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
557 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
558 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
559 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
560 " TexCoord -= OffsetVector * 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 " // LordHavoc: removed bias and simplified to one line\n"
567 " // LordHavoc: this is just a single sample offsetmapping...\n"
568 " TexCoordOffset += vec2(eyedir.x, -1.0 * eyedir.y) * OffsetMapping_Scale * texture2D(Texture_Normal, TexCoord).a;\n"
570 " // parallax mapping as described in the paper\n"
571 " // 'Parallax Mapping with Offset Limiting: A Per-Pixel Approximation of Uneven Surfaces' by Terry Welsh\n"
572 " // The paper provides code in the ARB fragment program assembly language\n"
573 " // I translated it to GLSL but may have done something wrong - SavageX\n"
574 " float height = texture2D(Texture_Normal, TexCoord).a;\n"
575 " height = (height - 0.5) * OffsetMapping_Scale; // bias and scale\n"
576 " TexCoordOffset += height * vec2(eyedir.x, -1.0 * eyedir.y);\n"
580 " // combine the diffuse textures (base, pants, shirt)\n"
581 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
582 "#ifdef USECOLORMAPPING\n"
583 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
589 "#ifdef MODE_LIGHTSOURCE\n"
592 " // get the surface normal and light normal\n"
593 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
594 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
596 " // calculate directional shading\n"
597 " color.rgb *= AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
598 "#ifdef USESPECULAR\n"
599 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
600 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
603 "#ifdef USECUBEFILTER\n"
604 " // apply light cubemap filter\n"
605 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
606 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
609 " // apply light color\n"
610 " color.rgb *= LightColor;\n"
612 " // apply attenuation\n"
614 " // the attenuation is (1-(x*x+y*y+z*z)) which gives a large bright\n"
615 " // center and sharp falloff at the edge, this is about the most efficient\n"
616 " // we can get away with as far as providing illumination.\n"
618 " // pow(1-(x*x+y*y+z*z), 4) is far more realistic but needs large lights to\n"
619 " // provide significant illumination, large = slow = pain.\n"
620 " color.rgb *= myhalf(max(1.0 - dot(CubeVector, CubeVector), 0.0));\n"
625 "#elif defined(MODE_LIGHTDIRECTION)\n"
626 " // directional model lighting\n"
628 " // get the surface normal and light normal\n"
629 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
630 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
632 " // calculate directional shading\n"
633 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
634 "#ifdef USESPECULAR\n"
635 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
636 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
642 "#elif defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
643 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
645 " // get the surface normal and light normal\n"
646 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
648 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
649 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
650 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
652 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
654 " // calculate directional shading\n"
655 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
656 "#ifdef USESPECULAR\n"
657 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
658 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
661 " // apply lightmap color\n"
662 " color.rgb = tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) + color.rgb * AmbientScale;\n"
665 "#else // MODE none (lightmap)\n"
666 " // apply lightmap color\n"
667 " color.rgb *= myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + myhvec3(AmbientScale);\n"
670 " color *= myhvec4(gl_Color);\n"
673 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
678 " myhalf fog = myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0)).x);\n"
679 " color.rgb = color.rgb * fog + FogColor * (1.0 - fog);\n"
682 " color.rgb *= SceneBrightness;\n"
684 " gl_FragColor = vec4(color);\n"
687 "#endif // FRAGMENT_SHADER\n"
690 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
691 const char *permutationinfo[][2] =
693 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
694 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
697 {"#define USEGLOW\n", " glow"},
698 {"#define USEFOG\n", " fog"},
699 {"#define USECOLORMAPPING\n", " colormapping"},
700 {"#define USESPECULAR\n", " specular"},
701 {"#define USECUBEFILTER\n", " cubefilter"},
702 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
703 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
707 void R_GLSL_CompilePermutation(int permutation)
710 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
711 int vertstrings_count;
712 int fragstrings_count;
714 const char *vertstrings_list[SHADERPERMUTATION_COUNT+1];
715 const char *fragstrings_list[SHADERPERMUTATION_COUNT+1];
716 char permutationname[256];
720 vertstrings_list[0] = "#define VERTEX_SHADER\n";
721 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
722 vertstrings_count = 1;
723 fragstrings_count = 1;
724 permutationname[0] = 0;
725 for (i = 0;permutationinfo[i][0];i++)
727 if (permutation & (1<<i))
729 vertstrings_list[vertstrings_count++] = permutationinfo[i][0];
730 fragstrings_list[fragstrings_count++] = permutationinfo[i][0];
731 strlcat(permutationname, permutationinfo[i][1], sizeof(permutationname));
735 // keep line numbers correct
736 vertstrings_list[vertstrings_count++] = "\n";
737 fragstrings_list[fragstrings_count++] = "\n";
740 shaderstring = (char *)FS_LoadFile("glsl/default.glsl", r_main_mempool, false, NULL);
743 Con_DPrintf("GLSL shader text loaded from disk\n");
744 vertstrings_list[vertstrings_count++] = shaderstring;
745 fragstrings_list[fragstrings_count++] = shaderstring;
749 vertstrings_list[vertstrings_count++] = builtinshaderstring;
750 fragstrings_list[fragstrings_count++] = builtinshaderstring;
752 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, fragstrings_count, fragstrings_list);
756 qglUseProgramObjectARB(p->program);CHECKGLERROR
757 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
758 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
759 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
760 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
761 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
762 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
763 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
764 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
765 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
766 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
767 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
768 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
769 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
770 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
771 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
772 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
773 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
774 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
775 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
776 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
777 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
778 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
779 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
780 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
781 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
782 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
783 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
784 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
785 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
786 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
787 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
788 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
789 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
790 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
791 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
792 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
793 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
794 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
796 qglUseProgramObjectARB(0);CHECKGLERROR
799 Con_Printf("permutation%s failed for shader %s, some features may not work properly!\n", permutationname, "glsl/default.glsl");
801 Mem_Free(shaderstring);
804 void R_GLSL_Restart_f(void)
807 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
808 if (r_glsl_permutations[i].program)
809 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
810 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
813 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting)
815 // select a permutation of the lighting shader appropriate to this
816 // combination of texture, entity, light source, and fogging, only use the
817 // minimum features necessary to avoid wasting rendering time in the
818 // fragment shader on features that are not being used
820 float specularscale = rsurface_texture->specularscale;
821 r_glsl_permutation = NULL;
822 if (r_shadow_rtlight)
824 permutation |= SHADERPERMUTATION_MODE_LIGHTSOURCE;
825 specularscale *= r_shadow_rtlight->specularscale;
826 if (r_shadow_rtlight->currentcubemap != r_texture_whitecube)
827 permutation |= SHADERPERMUTATION_CUBEFILTER;
831 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
834 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTION;
835 else if (r_glsl_deluxemapping.integer >= 1 && rsurface_lightmaptexture)
837 if (r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
839 if (r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
840 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
842 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
844 else if (r_glsl_deluxemapping.integer >= 2) // fake mode
845 permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
848 if (rsurface_texture->currentskinframe->glow)
849 permutation |= SHADERPERMUTATION_GLOW;
851 if (specularscale > 0)
852 permutation |= SHADERPERMUTATION_SPECULAR;
853 if (r_refdef.fogenabled)
854 permutation |= SHADERPERMUTATION_FOG;
855 if (rsurface_texture->colormapping)
856 permutation |= SHADERPERMUTATION_COLORMAPPING;
857 if (r_glsl_offsetmapping.integer)
859 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
860 if (r_glsl_offsetmapping_reliefmapping.integer)
861 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
863 if (!r_glsl_permutations[permutation].program)
865 if (!r_glsl_permutations[permutation].compiled)
866 R_GLSL_CompilePermutation(permutation);
867 if (!r_glsl_permutations[permutation].program)
869 // remove features until we find a valid permutation
871 for (i = SHADERPERMUTATION_COUNT-1;;i>>=1)
873 // reduce i more quickly whenever it would not remove any bits
877 if (!r_glsl_permutations[permutation].compiled)
878 R_GLSL_CompilePermutation(permutation);
879 if (r_glsl_permutations[permutation].program)
882 return 0; // utterly failed
886 r_glsl_permutation = r_glsl_permutations + permutation;
888 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
889 R_Mesh_TexMatrix(0, &rsurface_texture->currenttexmatrix);
890 if (permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE)
892 if (r_glsl_permutation->loc_Texture_Cube >= 0 && r_shadow_rtlight) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
893 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]);
894 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
895 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_shadow_rtlight->ambientscale);
896 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_shadow_rtlight->diffusescale);
897 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
899 else if (permutation & SHADERPERMUTATION_MODE_LIGHTDIRECTION)
901 if (r_glsl_permutation->loc_AmbientColor >= 0)
902 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor, rsurface_entity->modellight_ambient[0], rsurface_entity->modellight_ambient[1], rsurface_entity->modellight_ambient[2]);
903 if (r_glsl_permutation->loc_DiffuseColor >= 0)
904 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor, rsurface_entity->modellight_diffuse[0], rsurface_entity->modellight_diffuse[1], rsurface_entity->modellight_diffuse[2]);
905 if (r_glsl_permutation->loc_SpecularColor >= 0)
906 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);
907 if (r_glsl_permutation->loc_LightDir >= 0)
908 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface_entity->modellight_lightdir[0], rsurface_entity->modellight_lightdir[1], rsurface_entity->modellight_lightdir[2]);
912 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 2.0f / 128.0f);
913 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity * 2.0f);
914 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale * 2.0f);
916 if (r_glsl_permutation->loc_Texture_Normal >= 0) R_Mesh_TexBind(0, R_GetTexture(rsurface_texture->currentskinframe->nmap));
917 if (r_glsl_permutation->loc_Texture_Color >= 0) R_Mesh_TexBind(1, R_GetTexture(rsurface_texture->basetexture));
918 if (r_glsl_permutation->loc_Texture_Gloss >= 0) R_Mesh_TexBind(2, R_GetTexture(rsurface_texture->glosstexture));
919 //if (r_glsl_permutation->loc_Texture_Cube >= 0 && permutation & SHADERPERMUTATION_MODE_LIGHTSOURCE) R_Mesh_TexBindCubeMap(3, R_GetTexture(r_shadow_rtlight->currentcubemap));
920 if (r_glsl_permutation->loc_Texture_FogMask >= 0) R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
921 if (r_glsl_permutation->loc_Texture_Pants >= 0) R_Mesh_TexBind(5, R_GetTexture(rsurface_texture->currentskinframe->pants));
922 if (r_glsl_permutation->loc_Texture_Shirt >= 0) R_Mesh_TexBind(6, R_GetTexture(rsurface_texture->currentskinframe->shirt));
923 //if (r_glsl_permutation->loc_Texture_Lightmap >= 0) R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
924 //if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
925 if (r_glsl_permutation->loc_Texture_Glow >= 0) R_Mesh_TexBind(9, R_GetTexture(rsurface_texture->currentskinframe->glow));
926 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
927 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
928 if (r_glsl_permutation->loc_FogColor >= 0)
930 // additive passes are only darkened by fog, not tinted
931 if (r_shadow_rtlight || (rsurface_texture->currentmaterialflags & MATERIALFLAG_ADD))
932 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
934 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
936 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface_modelorg[0], rsurface_modelorg[1], rsurface_modelorg[2]);
937 if (r_glsl_permutation->loc_Color_Pants >= 0)
939 if (rsurface_texture->currentskinframe->pants)
940 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface_entity->colormap_pantscolor[0], rsurface_entity->colormap_pantscolor[1], rsurface_entity->colormap_pantscolor[2]);
942 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
944 if (r_glsl_permutation->loc_Color_Shirt >= 0)
946 if (rsurface_texture->currentskinframe->shirt)
947 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface_entity->colormap_shirtcolor[0], rsurface_entity->colormap_shirtcolor[1], rsurface_entity->colormap_shirtcolor[2]);
949 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
951 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
952 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface_texture->specularpower);
953 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
958 void R_SwitchSurfaceShader(int permutation)
960 if (r_glsl_permutation != r_glsl_permutations + permutation)
962 r_glsl_permutation = r_glsl_permutations + permutation;
964 qglUseProgramObjectARB(r_glsl_permutation->program);
969 void gl_main_start(void)
971 r_main_texturepool = R_AllocTexturePool();
972 R_BuildBlankTextures();
974 if (gl_texturecubemap)
977 R_BuildNormalizationCube();
980 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
981 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
984 void gl_main_shutdown(void)
986 R_FreeTexturePool(&r_main_texturepool);
987 r_texture_blanknormalmap = NULL;
988 r_texture_white = NULL;
989 r_texture_black = NULL;
990 r_texture_whitecube = NULL;
991 r_texture_normalizationcube = NULL;
992 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
996 extern void CL_ParseEntityLump(char *entitystring);
997 void gl_main_newmap(void)
999 // FIXME: move this code to client
1001 char *entities, entname[MAX_QPATH];
1004 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1005 l = (int)strlen(entname) - 4;
1006 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1008 memcpy(entname + l, ".ent", 5);
1009 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1011 CL_ParseEntityLump(entities);
1016 if (cl.worldmodel->brush.entities)
1017 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1021 void GL_Main_Init(void)
1023 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1025 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed\n");
1026 FOG_registercvars(); // FIXME: move this fog stuff to client?
1027 Cvar_RegisterVariable(&r_nearclip);
1028 Cvar_RegisterVariable(&r_showsurfaces);
1029 Cvar_RegisterVariable(&r_showtris);
1030 Cvar_RegisterVariable(&r_shownormals);
1031 Cvar_RegisterVariable(&r_showlighting);
1032 Cvar_RegisterVariable(&r_showshadowvolumes);
1033 Cvar_RegisterVariable(&r_showcollisionbrushes);
1034 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1035 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1036 Cvar_RegisterVariable(&r_showdisabledepthtest);
1037 Cvar_RegisterVariable(&r_drawportals);
1038 Cvar_RegisterVariable(&r_drawentities);
1039 Cvar_RegisterVariable(&r_drawviewmodel);
1040 Cvar_RegisterVariable(&r_speeds);
1041 Cvar_RegisterVariable(&r_fullbrights);
1042 Cvar_RegisterVariable(&r_wateralpha);
1043 Cvar_RegisterVariable(&r_dynamic);
1044 Cvar_RegisterVariable(&r_fullbright);
1045 Cvar_RegisterVariable(&r_shadows);
1046 Cvar_RegisterVariable(&r_shadows_throwdistance);
1047 Cvar_RegisterVariable(&r_q1bsp_skymasking);
1048 Cvar_RegisterVariable(&r_textureunits);
1049 Cvar_RegisterVariable(&r_glsl);
1050 Cvar_RegisterVariable(&r_glsl_offsetmapping);
1051 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
1052 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
1053 Cvar_RegisterVariable(&r_glsl_deluxemapping);
1054 Cvar_RegisterVariable(&r_lerpsprites);
1055 Cvar_RegisterVariable(&r_lerpmodels);
1056 Cvar_RegisterVariable(&r_waterscroll);
1057 Cvar_RegisterVariable(&r_bloom);
1058 Cvar_RegisterVariable(&r_bloom_colorscale);
1059 Cvar_RegisterVariable(&r_bloom_brighten);
1060 Cvar_RegisterVariable(&r_bloom_blur);
1061 Cvar_RegisterVariable(&r_bloom_resolution);
1062 Cvar_RegisterVariable(&r_bloom_colorexponent);
1063 Cvar_RegisterVariable(&r_bloom_colorsubtract);
1064 Cvar_RegisterVariable(&r_hdr);
1065 Cvar_RegisterVariable(&r_hdr_scenebrightness);
1066 Cvar_RegisterVariable(&r_hdr_glowintensity);
1067 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
1068 Cvar_RegisterVariable(&developer_texturelogging);
1069 Cvar_RegisterVariable(&gl_lightmaps);
1070 Cvar_RegisterVariable(&r_test);
1071 Cvar_RegisterVariable(&r_batchmode);
1072 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
1073 Cvar_SetValue("r_fullbrights", 0);
1074 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
1077 extern void R_Textures_Init(void);
1078 extern void GL_Draw_Init(void);
1079 extern void GL_Main_Init(void);
1080 extern void R_Shadow_Init(void);
1081 extern void R_Sky_Init(void);
1082 extern void GL_Surf_Init(void);
1083 extern void R_Light_Init(void);
1084 extern void R_Particles_Init(void);
1085 extern void R_Explosion_Init(void);
1086 extern void gl_backend_init(void);
1087 extern void Sbar_Init(void);
1088 extern void R_LightningBeams_Init(void);
1089 extern void Mod_RenderInit(void);
1091 void Render_Init(void)
1104 R_LightningBeams_Init();
1113 extern char *ENGINE_EXTENSIONS;
1116 VID_CheckExtensions();
1118 // LordHavoc: report supported extensions
1119 Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
1121 // clear to black (loading plaque will be seen over this)
1123 qglClearColor(0,0,0,1);CHECKGLERROR
1124 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
1127 int R_CullBox(const vec3_t mins, const vec3_t maxs)
1131 for (i = 0;i < 4;i++)
1133 p = r_view.frustum + i;
1138 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1142 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
1146 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1150 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
1154 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1158 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
1162 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1166 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
1174 //==================================================================================
1176 static void R_UpdateEntityLighting(entity_render_t *ent)
1178 vec3_t tempdiffusenormal;
1180 // fetch the lighting from the worldmodel data
1181 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));
1182 VectorClear(ent->modellight_diffuse);
1183 VectorClear(tempdiffusenormal);
1184 if ((ent->flags & RENDER_LIGHT) && r_refdef.worldmodel && r_refdef.worldmodel->brush.LightPoint)
1187 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
1188 r_refdef.worldmodel->brush.LightPoint(r_refdef.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
1191 VectorSet(ent->modellight_ambient, 1, 1, 1);
1193 // move the light direction into modelspace coordinates for lighting code
1194 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
1195 VectorNormalize(ent->modellight_lightdir);
1197 // scale ambient and directional light contributions according to rendering variables
1198 ent->modellight_ambient[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1199 ent->modellight_ambient[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1200 ent->modellight_ambient[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1201 ent->modellight_diffuse[0] *= ent->colormod[0] * r_refdef.lightmapintensity;
1202 ent->modellight_diffuse[1] *= ent->colormod[1] * r_refdef.lightmapintensity;
1203 ent->modellight_diffuse[2] *= ent->colormod[2] * r_refdef.lightmapintensity;
1206 static void R_View_UpdateEntityVisible (void)
1209 entity_render_t *ent;
1211 if (!r_drawentities.integer)
1214 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
1215 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
1217 // worldmodel can check visibility
1218 for (i = 0;i < r_refdef.numentities;i++)
1220 ent = r_refdef.entities[i];
1221 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));
1226 // no worldmodel or it can't check visibility
1227 for (i = 0;i < r_refdef.numentities;i++)
1229 ent = r_refdef.entities[i];
1230 r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs);
1234 // update entity lighting (even on hidden entities for r_shadows)
1235 for (i = 0;i < r_refdef.numentities;i++)
1236 R_UpdateEntityLighting(r_refdef.entities[i]);
1239 // only used if skyrendermasked, and normally returns false
1240 int R_DrawBrushModelsSky (void)
1243 entity_render_t *ent;
1245 if (!r_drawentities.integer)
1249 for (i = 0;i < r_refdef.numentities;i++)
1251 if (!r_viewcache.entityvisible[i])
1253 ent = r_refdef.entities[i];
1254 if (!ent->model || !ent->model->DrawSky)
1256 ent->model->DrawSky(ent);
1262 void R_DrawNoModel(entity_render_t *ent);
1263 void R_DrawModels(void)
1266 entity_render_t *ent;
1268 if (!r_drawentities.integer)
1271 for (i = 0;i < r_refdef.numentities;i++)
1273 if (!r_viewcache.entityvisible[i])
1275 ent = r_refdef.entities[i];
1276 r_refdef.stats.entities++;
1277 if (ent->model && ent->model->Draw != NULL)
1278 ent->model->Draw(ent);
1284 static void R_View_SetFrustum(void)
1286 // break apart the view matrix into vectors for various purposes
1287 Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
1288 VectorNegate(r_view.left, r_view.right);
1291 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
1292 r_view.frustum[0].normal[1] = 0 - 0;
1293 r_view.frustum[0].normal[2] = -1 - 0;
1294 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
1295 r_view.frustum[1].normal[1] = 0 + 0;
1296 r_view.frustum[1].normal[2] = -1 + 0;
1297 r_view.frustum[2].normal[0] = 0 - 0;
1298 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
1299 r_view.frustum[2].normal[2] = -1 - 0;
1300 r_view.frustum[3].normal[0] = 0 + 0;
1301 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
1302 r_view.frustum[3].normal[2] = -1 + 0;
1306 zNear = r_refdef.nearclip;
1307 nudge = 1.0 - 1.0 / (1<<23);
1308 r_view.frustum[4].normal[0] = 0 - 0;
1309 r_view.frustum[4].normal[1] = 0 - 0;
1310 r_view.frustum[4].normal[2] = -1 - -nudge;
1311 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
1312 r_view.frustum[5].normal[0] = 0 + 0;
1313 r_view.frustum[5].normal[1] = 0 + 0;
1314 r_view.frustum[5].normal[2] = -1 + -nudge;
1315 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
1321 r_view.frustum[0].normal[0] = m[3] - m[0];
1322 r_view.frustum[0].normal[1] = m[7] - m[4];
1323 r_view.frustum[0].normal[2] = m[11] - m[8];
1324 r_view.frustum[0].dist = m[15] - m[12];
1326 r_view.frustum[1].normal[0] = m[3] + m[0];
1327 r_view.frustum[1].normal[1] = m[7] + m[4];
1328 r_view.frustum[1].normal[2] = m[11] + m[8];
1329 r_view.frustum[1].dist = m[15] + m[12];
1331 r_view.frustum[2].normal[0] = m[3] - m[1];
1332 r_view.frustum[2].normal[1] = m[7] - m[5];
1333 r_view.frustum[2].normal[2] = m[11] - m[9];
1334 r_view.frustum[2].dist = m[15] - m[13];
1336 r_view.frustum[3].normal[0] = m[3] + m[1];
1337 r_view.frustum[3].normal[1] = m[7] + m[5];
1338 r_view.frustum[3].normal[2] = m[11] + m[9];
1339 r_view.frustum[3].dist = m[15] + m[13];
1341 r_view.frustum[4].normal[0] = m[3] - m[2];
1342 r_view.frustum[4].normal[1] = m[7] - m[6];
1343 r_view.frustum[4].normal[2] = m[11] - m[10];
1344 r_view.frustum[4].dist = m[15] - m[14];
1346 r_view.frustum[5].normal[0] = m[3] + m[2];
1347 r_view.frustum[5].normal[1] = m[7] + m[6];
1348 r_view.frustum[5].normal[2] = m[11] + m[10];
1349 r_view.frustum[5].dist = m[15] + m[14];
1354 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_x, r_view.left, r_view.frustum[0].normal);
1355 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_x, r_view.left, r_view.frustum[1].normal);
1356 VectorMAM(1, r_view.forward, 1.0 / -r_view.frustum_y, r_view.up, r_view.frustum[2].normal);
1357 VectorMAM(1, r_view.forward, 1.0 / r_view.frustum_y, r_view.up, r_view.frustum[3].normal);
1358 VectorCopy(r_view.forward, r_view.frustum[4].normal);
1359 VectorNormalize(r_view.frustum[0].normal);
1360 VectorNormalize(r_view.frustum[1].normal);
1361 VectorNormalize(r_view.frustum[2].normal);
1362 VectorNormalize(r_view.frustum[3].normal);
1363 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
1364 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
1365 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
1366 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
1367 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
1368 PlaneClassify(&r_view.frustum[0]);
1369 PlaneClassify(&r_view.frustum[1]);
1370 PlaneClassify(&r_view.frustum[2]);
1371 PlaneClassify(&r_view.frustum[3]);
1372 PlaneClassify(&r_view.frustum[4]);
1374 // LordHavoc: note to all quake engine coders, Quake had a special case
1375 // for 90 degrees which assumed a square view (wrong), so I removed it,
1376 // Quake2 has it disabled as well.
1378 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
1379 //RotatePointAroundVector( r_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
1380 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
1381 //PlaneClassify(&frustum[0]);
1383 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
1384 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
1385 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
1386 //PlaneClassify(&frustum[1]);
1388 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
1389 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
1390 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
1391 //PlaneClassify(&frustum[2]);
1393 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
1394 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
1395 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
1396 //PlaneClassify(&frustum[3]);
1399 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
1400 //r_view.frustum[4].dist = DotProduct (r_view.origin, frustum[4].normal) + r_nearclip.value;
1401 //PlaneClassify(&frustum[4]);
1404 void R_View_Update(void)
1406 R_View_SetFrustum();
1407 R_View_WorldVisibility();
1408 R_View_UpdateEntityVisible();
1411 void R_SetupView(const matrix4x4_t *matrix)
1413 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1414 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1416 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1418 GL_SetupView_Orientation_FromEntity(matrix);
1421 void R_ResetViewRendering2D(void)
1423 if (gl_support_fragment_shader)
1425 qglUseProgramObjectARB(0);CHECKGLERROR
1430 // GL is weird because it's bottom to top, r_view.y is top to bottom
1431 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1432 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1433 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1434 GL_Color(1, 1, 1, 1);
1435 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1436 GL_BlendFunc(GL_ONE, GL_ZERO);
1437 GL_AlphaTest(false);
1438 GL_ScissorTest(false);
1439 GL_DepthMask(false);
1440 GL_DepthTest(false);
1441 R_Mesh_Matrix(&identitymatrix);
1442 R_Mesh_ResetTextureState();
1443 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1444 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1445 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1446 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1447 qglStencilMask(~0);CHECKGLERROR
1448 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1449 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1450 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1453 void R_ResetViewRendering3D(void)
1455 if (gl_support_fragment_shader)
1457 qglUseProgramObjectARB(0);CHECKGLERROR
1462 // GL is weird because it's bottom to top, r_view.y is top to bottom
1463 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1464 R_SetupView(&r_view.matrix);
1465 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1466 GL_Color(1, 1, 1, 1);
1467 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1468 GL_BlendFunc(GL_ONE, GL_ZERO);
1469 GL_AlphaTest(false);
1470 GL_ScissorTest(true);
1473 R_Mesh_Matrix(&identitymatrix);
1474 R_Mesh_ResetTextureState();
1475 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1476 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1477 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1478 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1479 qglStencilMask(~0);CHECKGLERROR
1480 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
1481 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
1482 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
1486 R_Bloom_SetupShader(
1488 "// written by Forest 'LordHavoc' Hale\n"
1490 "// common definitions between vertex shader and fragment shader:\n"
1492 "#ifdef __GLSL_CG_DATA_TYPES\n"
1493 "#define myhalf half\n"
1494 "#define myhvec2 hvec2\n"
1495 "#define myhvec3 hvec3\n"
1496 "#define myhvec4 hvec4\n"
1498 "#define myhalf float\n"
1499 "#define myhvec2 vec2\n"
1500 "#define myhvec3 vec3\n"
1501 "#define myhvec4 vec4\n"
1504 "varying vec2 ScreenTexCoord;\n"
1505 "varying vec2 BloomTexCoord;\n"
1510 "// vertex shader specific:\n"
1511 "#ifdef VERTEX_SHADER\n"
1515 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
1516 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
1517 " // transform vertex to camera space, using ftransform to match non-VS\n"
1519 " gl_Position = ftransform();\n"
1522 "#endif // VERTEX_SHADER\n"
1527 "// fragment shader specific:\n"
1528 "#ifdef FRAGMENT_SHADER\n"
1533 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
1534 " for (x = -BLUR_X;x <= BLUR_X;x++)
1535 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1536 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1537 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1538 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1540 " gl_FragColor = vec4(color);\n"
1543 "#endif // FRAGMENT_SHADER\n"
1546 void R_RenderScene(void);
1548 void R_Bloom_StartFrame(void)
1550 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
1552 // set bloomwidth and bloomheight to the bloom resolution that will be
1553 // used (often less than the screen resolution for faster rendering)
1554 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1555 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
1556 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
1558 // calculate desired texture sizes
1559 if (gl_support_arb_texture_non_power_of_two)
1561 screentexturewidth = r_view.width;
1562 screentextureheight = r_view.height;
1563 bloomtexturewidth = r_bloomstate.bloomwidth;
1564 bloomtextureheight = r_bloomstate.bloomheight;
1568 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
1569 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
1570 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
1571 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
1576 screentexturewidth = screentextureheight = 0;
1578 else if (r_bloom.integer)
1583 screentexturewidth = screentextureheight = 0;
1584 bloomtexturewidth = bloomtextureheight = 0;
1587 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)
1589 // can't use bloom if the parameters are too weird
1590 // can't use bloom if the card does not support the texture size
1591 if (r_bloomstate.texture_screen)
1592 R_FreeTexture(r_bloomstate.texture_screen);
1593 if (r_bloomstate.texture_bloom)
1594 R_FreeTexture(r_bloomstate.texture_bloom);
1595 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1599 r_bloomstate.enabled = true;
1600 r_bloomstate.hdr = r_hdr.integer != 0;
1602 // allocate textures as needed
1603 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
1605 if (r_bloomstate.texture_screen)
1606 R_FreeTexture(r_bloomstate.texture_screen);
1607 r_bloomstate.texture_screen = NULL;
1608 r_bloomstate.screentexturewidth = screentexturewidth;
1609 r_bloomstate.screentextureheight = screentextureheight;
1610 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
1611 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);
1613 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
1615 if (r_bloomstate.texture_bloom)
1616 R_FreeTexture(r_bloomstate.texture_bloom);
1617 r_bloomstate.texture_bloom = NULL;
1618 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
1619 r_bloomstate.bloomtextureheight = bloomtextureheight;
1620 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
1621 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);
1624 // set up a texcoord array for the full resolution screen image
1625 // (we have to keep this around to copy back during final render)
1626 r_bloomstate.screentexcoord2f[0] = 0;
1627 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1628 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1629 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1630 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1631 r_bloomstate.screentexcoord2f[5] = 0;
1632 r_bloomstate.screentexcoord2f[6] = 0;
1633 r_bloomstate.screentexcoord2f[7] = 0;
1635 // set up a texcoord array for the reduced resolution bloom image
1636 // (which will be additive blended over the screen image)
1637 r_bloomstate.bloomtexcoord2f[0] = 0;
1638 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1639 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1640 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1641 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1642 r_bloomstate.bloomtexcoord2f[5] = 0;
1643 r_bloomstate.bloomtexcoord2f[6] = 0;
1644 r_bloomstate.bloomtexcoord2f[7] = 0;
1647 void R_Bloom_CopyScreenTexture(float colorscale)
1649 r_refdef.stats.bloom++;
1651 R_ResetViewRendering2D();
1652 R_Mesh_VertexPointer(r_screenvertex3f);
1653 R_Mesh_ColorPointer(NULL);
1654 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1655 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1657 // copy view into the screen texture
1658 GL_ActiveTexture(0);
1660 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
1661 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1663 // now scale it down to the bloom texture size
1665 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1666 GL_BlendFunc(GL_ONE, GL_ZERO);
1667 GL_Color(colorscale, colorscale, colorscale, 1);
1668 // TODO: optimize with multitexture or GLSL
1669 R_Mesh_Draw(0, 4, 2, polygonelements);
1670 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1672 // we now have a bloom image in the framebuffer
1673 // copy it into the bloom image texture for later processing
1674 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1675 GL_ActiveTexture(0);
1677 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
1678 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1681 void R_Bloom_CopyHDRTexture(void)
1683 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1684 GL_ActiveTexture(0);
1686 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
1687 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1690 void R_Bloom_MakeTexture(void)
1693 float xoffset, yoffset, r;
1695 r_refdef.stats.bloom++;
1697 R_ResetViewRendering2D();
1698 R_Mesh_VertexPointer(r_screenvertex3f);
1699 R_Mesh_ColorPointer(NULL);
1701 // we have a bloom image in the framebuffer
1703 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1705 for (x = 1;x < r_bloom_colorexponent.value;)
1708 r = bound(0, r_bloom_colorexponent.value / x, 1);
1709 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1710 GL_Color(r, r, r, 1);
1711 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1712 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1713 R_Mesh_Draw(0, 4, 2, polygonelements);
1714 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1716 // copy the vertically blurred bloom view to a texture
1717 GL_ActiveTexture(0);
1719 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
1720 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1723 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
1724 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1725 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f);
1727 for (dir = 0;dir < 2;dir++)
1729 // blend on at multiple vertical offsets to achieve a vertical blur
1730 // TODO: do offset blends using GLSL
1731 GL_BlendFunc(GL_ONE, GL_ZERO);
1732 for (x = -range;x <= range;x++)
1734 if (!dir){xoffset = 0;yoffset = x;}
1735 else {xoffset = x;yoffset = 0;}
1736 xoffset /= (float)r_bloomstate.bloomtexturewidth;
1737 yoffset /= (float)r_bloomstate.bloomtextureheight;
1738 // compute a texcoord array with the specified x and y offset
1739 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
1740 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1741 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1742 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1743 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1744 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
1745 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
1746 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
1747 // this r value looks like a 'dot' particle, fading sharply to
1748 // black at the edges
1749 // (probably not realistic but looks good enough)
1750 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
1751 //r = (dir ? 1.0f : r_bloom_brighten.value)/(range*2+1);
1752 r = (dir ? 1.0f : r_bloom_brighten.value)/(range*2+1)*(1 - x*x/(float)(range*range));
1753 GL_Color(r, r, r, 1);
1754 R_Mesh_Draw(0, 4, 2, polygonelements);
1755 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1756 GL_BlendFunc(GL_ONE, GL_ONE);
1759 // copy the vertically blurred bloom view to a texture
1760 GL_ActiveTexture(0);
1762 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
1763 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1766 // apply subtract last
1767 // (just like it would be in a GLSL shader)
1768 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
1770 GL_BlendFunc(GL_ONE, GL_ZERO);
1771 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1772 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1773 GL_Color(1, 1, 1, 1);
1774 R_Mesh_Draw(0, 4, 2, polygonelements);
1775 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1777 GL_BlendFunc(GL_ONE, GL_ONE);
1778 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
1779 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1780 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1781 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
1782 R_Mesh_Draw(0, 4, 2, polygonelements);
1783 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1784 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
1786 // copy the darkened bloom view to a texture
1787 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1788 GL_ActiveTexture(0);
1790 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
1791 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1795 void R_HDR_RenderBloomTexture(void)
1797 int oldwidth, oldheight;
1799 oldwidth = r_view.width;
1800 oldheight = r_view.height;
1801 r_view.width = r_bloomstate.bloomwidth;
1802 r_view.height = r_bloomstate.bloomheight;
1804 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
1805 // TODO: add exposure compensation features
1806 // TODO: add fp16 framebuffer support
1808 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
1811 R_ResetViewRendering2D();
1813 R_Bloom_CopyHDRTexture();
1814 R_Bloom_MakeTexture();
1816 R_ResetViewRendering3D();
1819 if (r_timereport_active)
1820 R_TimeReport("clear");
1823 // restore the view settings
1824 r_view.width = oldwidth;
1825 r_view.height = oldheight;
1828 static void R_BlendView(void)
1830 if (r_bloomstate.enabled && r_bloomstate.hdr)
1832 // render high dynamic range bloom effect
1833 // the bloom texture was made earlier this render, so we just need to
1834 // blend it onto the screen...
1835 R_ResetViewRendering2D();
1836 R_Mesh_VertexPointer(r_screenvertex3f);
1837 R_Mesh_ColorPointer(NULL);
1838 GL_Color(1, 1, 1, 1);
1839 GL_BlendFunc(GL_ONE, GL_ONE);
1840 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1841 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1842 R_Mesh_Draw(0, 4, 2, polygonelements);
1843 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1845 else if (r_bloomstate.enabled)
1847 // render simple bloom effect
1848 // copy the screen and shrink it and darken it for the bloom process
1849 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
1850 // make the bloom texture
1851 R_Bloom_MakeTexture();
1852 // put the original screen image back in place and blend the bloom
1854 R_ResetViewRendering2D();
1855 R_Mesh_VertexPointer(r_screenvertex3f);
1856 R_Mesh_ColorPointer(NULL);
1857 GL_Color(1, 1, 1, 1);
1858 GL_BlendFunc(GL_ONE, GL_ZERO);
1859 // do both in one pass if possible
1860 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1861 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1862 if (r_textureunits.integer >= 2 && gl_combine.integer)
1864 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1865 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
1866 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f);
1870 R_Mesh_Draw(0, 4, 2, polygonelements);
1871 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1872 // now blend on the bloom texture
1873 GL_BlendFunc(GL_ONE, GL_ONE);
1874 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1875 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1877 R_Mesh_Draw(0, 4, 2, polygonelements);
1878 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1880 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
1882 // apply a color tint to the whole view
1883 R_ResetViewRendering2D();
1884 R_Mesh_VertexPointer(r_screenvertex3f);
1885 R_Mesh_ColorPointer(NULL);
1886 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1887 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1888 R_Mesh_Draw(0, 4, 2, polygonelements);
1892 void R_RenderScene(void);
1894 matrix4x4_t r_waterscrollmatrix;
1896 void R_UpdateVariables(void)
1900 r_refdef.farclip = 4096;
1901 if (r_refdef.worldmodel)
1902 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1903 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
1905 r_refdef.polygonfactor = 0;
1906 r_refdef.polygonoffset = 0;
1907 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
1908 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
1910 r_refdef.rtworld = r_shadow_realtime_world.integer;
1911 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1912 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1913 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1914 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1915 if (r_showsurfaces.integer)
1917 r_refdef.rtworld = false;
1918 r_refdef.rtworldshadows = false;
1919 r_refdef.rtdlight = false;
1920 r_refdef.rtdlightshadows = false;
1921 r_refdef.lightmapintensity = 0;
1924 if (gamemode == GAME_NEHAHRA)
1926 if (gl_fogenable.integer)
1928 r_refdef.oldgl_fogenable = true;
1929 r_refdef.fog_density = gl_fogdensity.value;
1930 r_refdef.fog_red = gl_fogred.value;
1931 r_refdef.fog_green = gl_foggreen.value;
1932 r_refdef.fog_blue = gl_fogblue.value;
1934 else if (r_refdef.oldgl_fogenable)
1936 r_refdef.oldgl_fogenable = false;
1937 r_refdef.fog_density = 0;
1938 r_refdef.fog_red = 0;
1939 r_refdef.fog_green = 0;
1940 r_refdef.fog_blue = 0;
1943 if (r_refdef.fog_density)
1945 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
1946 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
1947 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
1949 if (r_refdef.fog_density)
1951 r_refdef.fogenabled = true;
1952 // this is the point where the fog reaches 0.9986 alpha, which we
1953 // consider a good enough cutoff point for the texture
1954 // (0.9986 * 256 == 255.6)
1955 r_refdef.fogrange = 400 / r_refdef.fog_density;
1956 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
1957 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
1958 // fog color was already set
1961 r_refdef.fogenabled = false;
1969 void R_RenderView(void)
1971 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1972 return; //Host_Error ("R_RenderView: NULL worldmodel");
1974 R_Shadow_UpdateWorldLightSelection();
1977 if (r_timereport_active)
1978 R_TimeReport("setup");
1981 if (r_timereport_active)
1982 R_TimeReport("visibility");
1984 R_ResetViewRendering3D();
1987 if (r_timereport_active)
1988 R_TimeReport("clear");
1990 R_Bloom_StartFrame();
1992 // this produces a bloom texture to be used in R_BlendView() later
1994 R_HDR_RenderBloomTexture();
1996 r_view.colorscale = r_hdr_scenebrightness.value;
2000 if (r_timereport_active)
2001 R_TimeReport("blendview");
2003 GL_Scissor(0, 0, vid.width, vid.height);
2004 GL_ScissorTest(false);
2008 extern void R_DrawLightningBeams (void);
2009 extern void VM_AddPolygonsToMeshQueue (void);
2010 extern void R_DrawPortals (void);
2011 void R_RenderScene(void)
2013 // don't let sound skip if going slow
2014 if (r_refdef.extraupdate)
2017 R_ResetViewRendering3D();
2019 R_MeshQueue_BeginScene();
2023 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);
2025 if (cl.csqc_vidvars.drawworld)
2027 // don't let sound skip if going slow
2028 if (r_refdef.extraupdate)
2031 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2033 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2034 if (r_timereport_active)
2035 R_TimeReport("worldsky");
2038 if (R_DrawBrushModelsSky() && r_timereport_active)
2039 R_TimeReport("bmodelsky");
2041 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2043 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2044 if (r_timereport_active)
2045 R_TimeReport("world");
2049 // don't let sound skip if going slow
2050 if (r_refdef.extraupdate)
2054 if (r_timereport_active)
2055 R_TimeReport("models");
2057 // don't let sound skip if going slow
2058 if (r_refdef.extraupdate)
2061 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2063 R_DrawModelShadows();
2065 R_ResetViewRendering3D();
2067 // don't let sound skip if going slow
2068 if (r_refdef.extraupdate)
2072 R_ShadowVolumeLighting(false);
2073 if (r_timereport_active)
2074 R_TimeReport("rtlights");
2076 // don't let sound skip if going slow
2077 if (r_refdef.extraupdate)
2080 if (cl.csqc_vidvars.drawworld)
2082 R_DrawLightningBeams();
2083 if (r_timereport_active)
2084 R_TimeReport("lightning");
2087 if (r_timereport_active)
2088 R_TimeReport("particles");
2091 if (r_timereport_active)
2092 R_TimeReport("explosions");
2095 if (gl_support_fragment_shader)
2097 qglUseProgramObjectARB(0);CHECKGLERROR
2099 VM_AddPolygonsToMeshQueue();
2101 if (r_drawportals.integer)
2104 if (r_timereport_active)
2105 R_TimeReport("portals");
2108 if (gl_support_fragment_shader)
2110 qglUseProgramObjectARB(0);CHECKGLERROR
2112 R_MeshQueue_RenderTransparent();
2113 if (r_timereport_active)
2114 R_TimeReport("drawtrans");
2116 if (gl_support_fragment_shader)
2118 qglUseProgramObjectARB(0);CHECKGLERROR
2121 if (cl.csqc_vidvars.drawworld)
2124 if (r_timereport_active)
2125 R_TimeReport("coronas");
2128 // don't let sound skip if going slow
2129 if (r_refdef.extraupdate)
2132 R_ResetViewRendering2D();
2136 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2139 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2140 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2141 GL_DepthMask(false);
2143 R_Mesh_Matrix(&identitymatrix);
2145 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2146 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2147 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2148 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2149 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2150 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2151 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2152 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2153 R_FillColors(color, 8, cr, cg, cb, ca);
2154 if (r_refdef.fogenabled)
2156 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2158 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
2160 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2161 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2162 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2165 R_Mesh_VertexPointer(vertex3f);
2166 R_Mesh_ColorPointer(color);
2167 R_Mesh_ResetTextureState();
2172 int nomodelelements[24] =
2184 float nomodelvertex3f[6*3] =
2194 float nomodelcolor4f[6*4] =
2196 0.0f, 0.0f, 0.5f, 1.0f,
2197 0.0f, 0.0f, 0.5f, 1.0f,
2198 0.0f, 0.5f, 0.0f, 1.0f,
2199 0.0f, 0.5f, 0.0f, 1.0f,
2200 0.5f, 0.0f, 0.0f, 1.0f,
2201 0.5f, 0.0f, 0.0f, 1.0f
2204 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2209 // this is only called once per entity so numsurfaces is always 1, and
2210 // surfacelist is always {0}, so this code does not handle batches
2211 R_Mesh_Matrix(&ent->matrix);
2213 if (ent->flags & EF_ADDITIVE)
2215 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2216 GL_DepthMask(false);
2218 else if (ent->alpha < 1)
2220 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2221 GL_DepthMask(false);
2225 GL_BlendFunc(GL_ONE, GL_ZERO);
2228 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2229 GL_CullFace((ent->flags & RENDER_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
2230 R_Mesh_VertexPointer(nomodelvertex3f);
2231 if (r_refdef.fogenabled)
2234 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2235 R_Mesh_ColorPointer(color4f);
2236 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2237 f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin));
2239 for (i = 0, c = color4f;i < 6;i++, c += 4)
2241 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2242 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2243 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2247 else if (ent->alpha != 1)
2249 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2250 R_Mesh_ColorPointer(color4f);
2251 for (i = 0, c = color4f;i < 6;i++, c += 4)
2255 R_Mesh_ColorPointer(nomodelcolor4f);
2256 R_Mesh_ResetTextureState();
2257 R_Mesh_Draw(0, 6, 8, nomodelelements);
2260 void R_DrawNoModel(entity_render_t *ent)
2263 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2264 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2265 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2267 // R_DrawNoModelCallback(ent, 0);
2270 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2272 vec3_t right1, right2, diff, normal;
2274 VectorSubtract (org2, org1, normal);
2276 // calculate 'right' vector for start
2277 VectorSubtract (r_view.origin, org1, diff);
2278 CrossProduct (normal, diff, right1);
2279 VectorNormalize (right1);
2281 // calculate 'right' vector for end
2282 VectorSubtract (r_view.origin, org2, diff);
2283 CrossProduct (normal, diff, right2);
2284 VectorNormalize (right2);
2286 vert[ 0] = org1[0] + width * right1[0];
2287 vert[ 1] = org1[1] + width * right1[1];
2288 vert[ 2] = org1[2] + width * right1[2];
2289 vert[ 3] = org1[0] - width * right1[0];
2290 vert[ 4] = org1[1] - width * right1[1];
2291 vert[ 5] = org1[2] - width * right1[2];
2292 vert[ 6] = org2[0] - width * right2[0];
2293 vert[ 7] = org2[1] - width * right2[1];
2294 vert[ 8] = org2[2] - width * right2[2];
2295 vert[ 9] = org2[0] + width * right2[0];
2296 vert[10] = org2[1] + width * right2[1];
2297 vert[11] = org2[2] + width * right2[2];
2300 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2302 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)
2304 float fog = 0.0f, ifog;
2307 if (r_refdef.fogenabled)
2308 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2311 R_Mesh_Matrix(&identitymatrix);
2312 GL_BlendFunc(blendfunc1, blendfunc2);
2313 GL_DepthMask(false);
2314 GL_DepthTest(!depthdisable);
2316 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2317 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2318 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2319 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2320 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2321 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2322 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2323 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2324 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2325 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2326 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2327 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2329 R_Mesh_VertexPointer(vertex3f);
2330 R_Mesh_ColorPointer(NULL);
2331 R_Mesh_ResetTextureState();
2332 R_Mesh_TexBind(0, R_GetTexture(texture));
2333 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2334 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2335 GL_Color(cr * ifog * r_view.colorscale, cg * ifog * r_view.colorscale, cb * ifog * r_view.colorscale, ca);
2336 R_Mesh_Draw(0, 4, 2, polygonelements);
2338 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2340 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2341 GL_BlendFunc(blendfunc1, GL_ONE);
2342 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);
2343 R_Mesh_Draw(0, 4, 2, polygonelements);
2347 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2352 VectorSet(v, x, y, z);
2353 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2354 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2356 if (i == mesh->numvertices)
2358 if (mesh->numvertices < mesh->maxvertices)
2360 VectorCopy(v, vertex3f);
2361 mesh->numvertices++;
2363 return mesh->numvertices;
2369 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2373 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2374 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2375 e = mesh->element3i + mesh->numtriangles * 3;
2376 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2378 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2379 if (mesh->numtriangles < mesh->maxtriangles)
2384 mesh->numtriangles++;
2386 element[1] = element[2];
2390 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2394 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2395 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2396 e = mesh->element3i + mesh->numtriangles * 3;
2397 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2399 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2400 if (mesh->numtriangles < mesh->maxtriangles)
2405 mesh->numtriangles++;
2407 element[1] = element[2];
2411 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
2412 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2414 int planenum, planenum2;
2417 mplane_t *plane, *plane2;
2419 double temppoints[2][256*3];
2420 // figure out how large a bounding box we need to properly compute this brush
2422 for (w = 0;w < numplanes;w++)
2423 maxdist = max(maxdist, planes[w].dist);
2424 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
2425 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
2426 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2430 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
2431 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2433 if (planenum2 == planenum)
2435 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);
2438 if (tempnumpoints < 3)
2440 // generate elements forming a triangle fan for this polygon
2441 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
2445 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2448 R_Mesh_VertexPointer(brush->points->v);
2449 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2450 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);
2451 GL_LockArrays(0, brush->numpoints);
2452 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2453 GL_LockArrays(0, 0);
2456 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2459 if (!surface->num_collisiontriangles)
2461 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2462 i = (int)(((size_t)surface) / sizeof(msurface_t));
2463 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);
2464 GL_LockArrays(0, surface->num_collisionvertices);
2465 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2466 GL_LockArrays(0, 0);
2469 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)
2471 texturelayer_t *layer;
2472 layer = t->currentlayers + t->currentnumlayers++;
2474 layer->depthmask = depthmask;
2475 layer->blendfunc1 = blendfunc1;
2476 layer->blendfunc2 = blendfunc2;
2477 layer->texture = texture;
2478 layer->texmatrix = *matrix;
2479 layer->color[0] = r * r_view.colorscale;
2480 layer->color[1] = g * r_view.colorscale;
2481 layer->color[2] = b * r_view.colorscale;
2482 layer->color[3] = a;
2485 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2487 model_t *model = ent->model;
2489 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2490 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2492 // switch to an alternate material if this is a q1bsp animated material
2494 texture_t *texture = t;
2495 int s = ent->skinnum;
2496 if ((unsigned int)s >= (unsigned int)model->numskins)
2498 if (model->skinscenes)
2500 if (model->skinscenes[s].framecount > 1)
2501 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2503 s = model->skinscenes[s].firstframe;
2506 t = t + s * model->num_surfaces;
2509 // use an alternate animation if the entity's frame is not 0,
2510 // and only if the texture has an alternate animation
2511 if (ent->frame != 0 && t->anim_total[1])
2512 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2514 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2516 texture->currentframe = t;
2519 // pick a new currentskinframe if the material is animated
2520 if (t->numskinframes >= 2)
2521 t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
2523 t->currentmaterialflags = t->basematerialflags;
2524 t->currentalpha = ent->alpha;
2525 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
2526 t->currentalpha *= r_wateralpha.value;
2527 if (!(ent->flags & RENDER_LIGHT))
2528 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2529 if (ent->effects & EF_ADDITIVE)
2530 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2531 else if (t->currentalpha < 1)
2532 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2533 if (ent->effects & EF_NODEPTHTEST)
2534 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2535 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2536 t->currenttexmatrix = r_waterscrollmatrix;
2538 t->currenttexmatrix = identitymatrix;
2540 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2541 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2542 t->glosstexture = r_texture_white;
2543 t->specularpower = r_shadow_glossexponent.value;
2544 t->specularscale = 0;
2545 if (r_shadow_gloss.integer > 0)
2547 if (t->currentskinframe->gloss)
2549 if (r_shadow_glossintensity.value > 0)
2551 t->glosstexture = t->currentskinframe->gloss;
2552 t->specularscale = r_shadow_glossintensity.value;
2555 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2556 t->specularscale = r_shadow_gloss2intensity.value;
2559 t->currentnumlayers = 0;
2560 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2562 if (gl_lightmaps.integer)
2563 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2564 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2566 int blendfunc1, blendfunc2, depthmask;
2567 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2569 blendfunc1 = GL_SRC_ALPHA;
2570 blendfunc2 = GL_ONE;
2572 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2574 blendfunc1 = GL_SRC_ALPHA;
2575 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2577 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2579 blendfunc1 = t->customblendfunc[0];
2580 blendfunc2 = t->customblendfunc[1];
2584 blendfunc1 = GL_ONE;
2585 blendfunc2 = GL_ZERO;
2587 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2588 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2590 rtexture_t *currentbasetexture;
2592 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2593 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2594 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2595 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2597 // fullbright is not affected by r_refdef.lightmapintensity
2598 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2599 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2600 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);
2601 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2602 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);
2608 // q3bsp has no lightmap updates, so the lightstylevalue that
2609 // would normally be baked into the lightmap must be
2610 // applied to the color
2611 if (ent->model->type == mod_brushq3)
2612 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2613 colorscale *= r_refdef.lightmapintensity;
2614 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);
2615 if (r_ambient.value >= (1.0f/64.0f))
2616 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);
2617 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2619 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);
2620 if (r_ambient.value >= (1.0f/64.0f))
2621 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);
2623 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2625 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);
2626 if (r_ambient.value >= (1.0f/64.0f))
2627 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);
2630 if (t->currentskinframe->glow != NULL)
2631 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);
2632 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2634 // if this is opaque use alpha blend which will darken the earlier
2637 // if this is an alpha blended material, all the earlier passes
2638 // were darkened by fog already, so we only need to add the fog
2639 // color ontop through the fog mask texture
2641 // if this is an additive blended material, all the earlier passes
2642 // were darkened by fog already, and we should not add fog color
2643 // (because the background was not darkened, there is no fog color
2644 // that was lost behind it).
2645 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);
2652 void R_UpdateAllTextureInfo(entity_render_t *ent)
2656 for (i = 0;i < ent->model->num_textures;i++)
2657 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2660 int rsurface_array_size = 0;
2661 float *rsurface_array_modelvertex3f = NULL;
2662 float *rsurface_array_modelsvector3f = NULL;
2663 float *rsurface_array_modeltvector3f = NULL;
2664 float *rsurface_array_modelnormal3f = NULL;
2665 float *rsurface_array_deformedvertex3f = NULL;
2666 float *rsurface_array_deformedsvector3f = NULL;
2667 float *rsurface_array_deformedtvector3f = NULL;
2668 float *rsurface_array_deformednormal3f = NULL;
2669 float *rsurface_array_color4f = NULL;
2670 float *rsurface_array_texcoord3f = NULL;
2672 void R_Mesh_ResizeArrays(int newvertices)
2675 if (rsurface_array_size >= newvertices)
2677 if (rsurface_array_modelvertex3f)
2678 Mem_Free(rsurface_array_modelvertex3f);
2679 rsurface_array_size = (newvertices + 1023) & ~1023;
2680 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2681 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2682 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2683 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2684 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2685 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2686 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2687 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2688 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2689 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2690 rsurface_array_color4f = base + rsurface_array_size * 27;
2693 float *rsurface_modelvertex3f;
2694 float *rsurface_modelsvector3f;
2695 float *rsurface_modeltvector3f;
2696 float *rsurface_modelnormal3f;
2697 float *rsurface_vertex3f;
2698 float *rsurface_svector3f;
2699 float *rsurface_tvector3f;
2700 float *rsurface_normal3f;
2701 float *rsurface_lightmapcolor4f;
2702 vec3_t rsurface_modelorg;
2703 qboolean rsurface_generatedvertex;
2704 const entity_render_t *rsurface_entity;
2705 const model_t *rsurface_model;
2706 texture_t *rsurface_texture;
2707 rtexture_t *rsurface_lightmaptexture;
2708 rsurfmode_t rsurface_mode;
2709 texture_t *rsurface_glsl_texture;
2710 qboolean rsurface_glsl_uselightmap;
2712 void RSurf_CleanUp(void)
2715 if (rsurface_mode == RSURFMODE_GLSL)
2717 qglUseProgramObjectARB(0);CHECKGLERROR
2719 GL_AlphaTest(false);
2720 rsurface_mode = RSURFMODE_NONE;
2721 rsurface_lightmaptexture = NULL;
2722 rsurface_texture = NULL;
2723 rsurface_glsl_texture = NULL;
2724 rsurface_glsl_uselightmap = false;
2727 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2730 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2731 rsurface_entity = ent;
2732 rsurface_model = ent->model;
2733 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2734 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2735 R_Mesh_Matrix(&ent->matrix);
2736 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2737 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
2741 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2742 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2743 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2744 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2745 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2747 else if (wantnormals)
2749 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2750 rsurface_modelsvector3f = NULL;
2751 rsurface_modeltvector3f = NULL;
2752 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2753 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2757 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2758 rsurface_modelsvector3f = NULL;
2759 rsurface_modeltvector3f = NULL;
2760 rsurface_modelnormal3f = NULL;
2761 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2763 rsurface_generatedvertex = true;
2767 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2768 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2769 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2770 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2771 rsurface_generatedvertex = false;
2773 rsurface_vertex3f = rsurface_modelvertex3f;
2774 rsurface_svector3f = rsurface_modelsvector3f;
2775 rsurface_tvector3f = rsurface_modeltvector3f;
2776 rsurface_normal3f = rsurface_modelnormal3f;
2779 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2781 // 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
2782 if (rsurface_generatedvertex)
2784 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2785 generatetangents = true;
2786 if (generatetangents)
2787 generatenormals = true;
2788 if (generatenormals && !rsurface_modelnormal3f)
2790 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2791 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);
2793 if (generatetangents && !rsurface_modelsvector3f)
2795 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2796 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2797 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);
2800 // 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)
2801 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2803 int texturesurfaceindex;
2804 float center[3], forward[3], right[3], up[3], v[4][3];
2805 matrix4x4_t matrix1, imatrix1;
2806 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2807 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2808 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2809 // make deformed versions of only the model vertices used by the specified surfaces
2810 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2813 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2814 // a single autosprite surface can contain multiple sprites...
2815 for (j = 0;j < surface->num_vertices - 3;j += 4)
2817 VectorClear(center);
2818 for (i = 0;i < 4;i++)
2819 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2820 VectorScale(center, 0.25f, center);
2821 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2823 forward[0] = rsurface_modelorg[0] - center[0];
2824 forward[1] = rsurface_modelorg[1] - center[1];
2826 VectorNormalize(forward);
2827 right[0] = forward[1];
2828 right[1] = -forward[0];
2830 VectorSet(up, 0, 0, 1);
2832 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2833 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);
2834 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2835 for (i = 0;i < 4;i++)
2836 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2837 for (i = 0;i < 4;i++)
2838 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
2840 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);
2841 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);
2843 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2844 rsurface_svector3f = rsurface_array_deformedsvector3f;
2845 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2846 rsurface_normal3f = rsurface_array_deformednormal3f;
2850 rsurface_vertex3f = rsurface_modelvertex3f;
2851 rsurface_svector3f = rsurface_modelsvector3f;
2852 rsurface_tvector3f = rsurface_modeltvector3f;
2853 rsurface_normal3f = rsurface_modelnormal3f;
2855 R_Mesh_VertexPointer(rsurface_vertex3f);
2858 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2860 int texturesurfaceindex;
2861 const msurface_t *surface = texturesurfacelist[0];
2862 int firstvertex = surface->num_firstvertex;
2863 int endvertex = surface->num_firstvertex + surface->num_vertices;
2864 if (texturenumsurfaces == 1)
2866 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2867 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2869 else if (r_batchmode.integer == 2)
2871 #define MAXBATCHTRIANGLES 4096
2872 int batchtriangles = 0;
2873 int batchelements[MAXBATCHTRIANGLES*3];
2874 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2876 surface = texturesurfacelist[texturesurfaceindex];
2877 if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2879 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2882 if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2884 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2886 firstvertex = surface->num_firstvertex;
2887 endvertex = surface->num_firstvertex + surface->num_vertices;
2891 firstvertex = min(firstvertex, surface->num_firstvertex);
2892 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2894 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2895 batchtriangles += surface->num_triangles;
2898 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2900 else if (r_batchmode.integer == 1)
2902 int firsttriangle = 0;
2903 int endtriangle = -1;
2904 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2906 surface = texturesurfacelist[texturesurfaceindex];
2907 if (surface->num_firsttriangle != endtriangle)
2909 if (endtriangle > firsttriangle)
2911 GL_LockArrays(firstvertex, endvertex - firstvertex);
2912 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2914 firstvertex = surface->num_firstvertex;
2915 endvertex = surface->num_firstvertex + surface->num_vertices;
2916 firsttriangle = surface->num_firsttriangle;
2920 firstvertex = min(firstvertex, surface->num_firstvertex);
2921 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2923 endtriangle = surface->num_firsttriangle + surface->num_triangles;
2925 if (endtriangle > firsttriangle)
2927 GL_LockArrays(firstvertex, endvertex - firstvertex);
2928 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2933 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2935 surface = texturesurfacelist[texturesurfaceindex];
2936 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2937 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2942 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2944 int texturesurfaceindex;
2945 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2947 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2948 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2949 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);
2950 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2951 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2955 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2957 int texturesurfaceindex;
2965 vec3_t ambientcolor;
2966 vec3_t diffusecolor;
2968 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2969 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2970 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2971 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2972 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2973 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2974 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2975 if (VectorLength2(diffusecolor) > 0)
2977 // generate color arrays for the surfaces in this list
2978 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2980 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2981 int numverts = surface->num_vertices;
2982 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2983 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2984 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2985 // q3-style directional shading
2986 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2988 if ((f = DotProduct(c2, lightdir)) > 0)
2989 VectorMA(ambientcolor, f, diffusecolor, c);
2991 VectorCopy(ambientcolor, c);
3000 rsurface_lightmapcolor4f = rsurface_array_color4f;
3004 r = ambientcolor[0];
3005 g = ambientcolor[1];
3006 b = ambientcolor[2];
3007 rsurface_lightmapcolor4f = NULL;
3010 else if (lightmode >= 1 || !rsurface_lightmaptexture)
3012 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
3014 // generate color arrays for the surfaces in this list
3015 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3017 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3018 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
3020 if (surface->lightmapinfo->samples)
3022 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
3023 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
3024 VectorScale(lm, scale, c);
3025 if (surface->lightmapinfo->styles[1] != 255)
3027 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3029 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3030 VectorMA(c, scale, lm, c);
3031 if (surface->lightmapinfo->styles[2] != 255)
3034 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3035 VectorMA(c, scale, lm, c);
3036 if (surface->lightmapinfo->styles[3] != 255)
3039 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3040 VectorMA(c, scale, lm, c);
3050 rsurface_lightmapcolor4f = rsurface_array_color4f;
3053 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3058 rsurface_lightmapcolor4f = NULL;
3062 if (rsurface_lightmapcolor4f)
3064 // generate color arrays for the surfaces in this list
3065 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3067 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3068 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)
3070 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3080 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3082 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3083 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)
3085 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3093 rsurface_lightmapcolor4f = rsurface_array_color4f;
3095 if (applycolor && rsurface_lightmapcolor4f)
3097 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3099 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3100 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)
3108 rsurface_lightmapcolor4f = rsurface_array_color4f;
3110 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3111 GL_Color(r, g, b, a);
3112 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3115 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3117 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3119 rsurface_mode = RSURFMODE_SHOWSURFACES;
3121 GL_BlendFunc(GL_ONE, GL_ZERO);
3122 R_Mesh_ColorPointer(NULL);
3123 R_Mesh_ResetTextureState();
3125 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3126 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3129 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3131 // transparent sky would be ridiculous
3132 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3134 if (rsurface_mode != RSURFMODE_SKY)
3136 if (rsurface_mode == RSURFMODE_GLSL)
3138 qglUseProgramObjectARB(0);CHECKGLERROR
3140 rsurface_mode = RSURFMODE_SKY;
3144 skyrendernow = false;
3146 // restore entity matrix
3147 R_Mesh_Matrix(&rsurface_entity->matrix);
3150 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3151 // skymasking on them, and Quake3 never did sky masking (unlike
3152 // software Quake and software Quake2), so disable the sky masking
3153 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3154 // and skymasking also looks very bad when noclipping outside the
3155 // level, so don't use it then either.
3156 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3158 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3159 R_Mesh_ColorPointer(NULL);
3160 R_Mesh_ResetTextureState();
3161 if (skyrendermasked)
3163 // depth-only (masking)
3164 GL_ColorMask(0,0,0,0);
3165 // just to make sure that braindead drivers don't draw
3166 // anything despite that colormask...
3167 GL_BlendFunc(GL_ZERO, GL_ONE);
3172 GL_BlendFunc(GL_ONE, GL_ZERO);
3174 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3175 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3176 if (skyrendermasked)
3177 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3181 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3184 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3185 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3186 if (rsurface_mode != RSURFMODE_GLSL)
3188 rsurface_mode = RSURFMODE_GLSL;
3189 rsurface_glsl_texture = NULL;
3190 rsurface_glsl_uselightmap = false;
3191 R_Mesh_ResetTextureState();
3193 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
3195 rsurface_glsl_texture = rsurface_texture;
3196 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
3197 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3198 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3199 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3200 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
3201 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
3202 //if (r_glsl_deluxemapping.integer)
3203 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
3204 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3205 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3206 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3208 if (!r_glsl_permutation)
3210 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
3211 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3212 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3213 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3214 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3216 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3217 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3218 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3219 R_Mesh_ColorPointer(NULL);
3221 else if (rsurface_lightmaptexture)
3223 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
3224 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3225 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3226 R_Mesh_ColorPointer(NULL);
3230 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3231 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3232 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3233 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3235 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3238 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3240 // OpenGL 1.3 path - anything not completely ancient
3241 int texturesurfaceindex;
3243 qboolean applycolor;
3247 const texturelayer_t *layer;
3249 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3250 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3251 if (rsurface_mode != RSURFMODE_MULTIPASS)
3252 rsurface_mode = RSURFMODE_MULTIPASS;
3253 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3254 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3257 int layertexrgbscale;
3258 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3260 if (layerindex == 0)
3264 GL_AlphaTest(false);
3265 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3268 GL_DepthMask(layer->depthmask);
3269 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3270 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3272 layertexrgbscale = 4;
3273 VectorScale(layer->color, 0.25f, layercolor);
3275 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3277 layertexrgbscale = 2;
3278 VectorScale(layer->color, 0.5f, layercolor);
3282 layertexrgbscale = 1;
3283 VectorScale(layer->color, 1.0f, layercolor);
3285 layercolor[3] = layer->color[3];
3286 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3287 R_Mesh_ColorPointer(NULL);
3288 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3289 switch (layer->type)
3291 case TEXTURELAYERTYPE_LITTEXTURE:
3292 memset(&m, 0, sizeof(m));
3293 if (lightmode >= 1 || !rsurface_lightmaptexture)
3294 m.tex[0] = R_GetTexture(r_texture_white);
3296 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3297 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3298 m.tex[1] = R_GetTexture(layer->texture);
3299 m.texmatrix[1] = layer->texmatrix;
3300 m.texrgbscale[1] = layertexrgbscale;
3301 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3302 R_Mesh_TextureState(&m);
3303 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
3305 case TEXTURELAYERTYPE_TEXTURE:
3306 memset(&m, 0, sizeof(m));
3307 m.tex[0] = R_GetTexture(layer->texture);
3308 m.texmatrix[0] = layer->texmatrix;
3309 m.texrgbscale[0] = layertexrgbscale;
3310 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3311 R_Mesh_TextureState(&m);
3312 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3314 case TEXTURELAYERTYPE_FOG:
3315 memset(&m, 0, sizeof(m));
3316 m.texrgbscale[0] = layertexrgbscale;
3319 m.tex[0] = R_GetTexture(layer->texture);
3320 m.texmatrix[0] = layer->texmatrix;
3321 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3323 R_Mesh_TextureState(&m);
3324 // generate a color array for the fog pass
3325 R_Mesh_ColorPointer(rsurface_array_color4f);
3326 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3330 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3331 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)
3333 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3334 c[0] = layercolor[0];
3335 c[1] = layercolor[1];
3336 c[2] = layercolor[2];
3337 c[3] = f * layercolor[3];
3340 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3343 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3345 GL_LockArrays(0, 0);
3348 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3350 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3351 GL_AlphaTest(false);
3355 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3357 // OpenGL 1.1 - crusty old voodoo path
3358 int texturesurfaceindex;
3363 const texturelayer_t *layer;
3365 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3366 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3367 if (rsurface_mode != RSURFMODE_MULTIPASS)
3368 rsurface_mode = RSURFMODE_MULTIPASS;
3369 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3370 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3372 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3374 if (layerindex == 0)
3378 GL_AlphaTest(false);
3379 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3382 GL_DepthMask(layer->depthmask);
3383 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3384 R_Mesh_ColorPointer(NULL);
3385 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3386 switch (layer->type)
3388 case TEXTURELAYERTYPE_LITTEXTURE:
3389 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3391 // two-pass lit texture with 2x rgbscale
3392 // first the lightmap pass
3393 memset(&m, 0, sizeof(m));
3394 if (lightmode >= 1 || !rsurface_lightmaptexture)
3395 m.tex[0] = R_GetTexture(r_texture_white);
3397 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3398 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3399 R_Mesh_TextureState(&m);
3400 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3401 GL_LockArrays(0, 0);
3402 // then apply the texture to it
3403 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3404 memset(&m, 0, sizeof(m));
3405 m.tex[0] = R_GetTexture(layer->texture);
3406 m.texmatrix[0] = layer->texmatrix;
3407 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3408 R_Mesh_TextureState(&m);
3409 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);
3413 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3414 memset(&m, 0, sizeof(m));
3415 m.tex[0] = R_GetTexture(layer->texture);
3416 m.texmatrix[0] = layer->texmatrix;
3417 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3418 R_Mesh_TextureState(&m);
3419 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);
3422 case TEXTURELAYERTYPE_TEXTURE:
3423 // singletexture unlit texture with transparency support
3424 memset(&m, 0, sizeof(m));
3425 m.tex[0] = R_GetTexture(layer->texture);
3426 m.texmatrix[0] = layer->texmatrix;
3427 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3428 R_Mesh_TextureState(&m);
3429 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);
3431 case TEXTURELAYERTYPE_FOG:
3432 // singletexture fogging
3433 R_Mesh_ColorPointer(rsurface_array_color4f);
3436 memset(&m, 0, sizeof(m));
3437 m.tex[0] = R_GetTexture(layer->texture);
3438 m.texmatrix[0] = layer->texmatrix;
3439 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3440 R_Mesh_TextureState(&m);
3443 R_Mesh_ResetTextureState();
3444 // generate a color array for the fog pass
3445 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3449 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3450 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)
3452 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3453 c[0] = layer->color[0];
3454 c[1] = layer->color[1];
3455 c[2] = layer->color[2];
3456 c[3] = f * layer->color[3];
3459 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3462 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3464 GL_LockArrays(0, 0);
3467 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3469 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3470 GL_AlphaTest(false);
3474 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3476 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3478 r_shadow_rtlight = NULL;
3479 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3481 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3482 GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3483 if (r_showsurfaces.integer)
3484 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3485 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3486 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3487 else if (rsurface_texture->currentnumlayers)
3489 if (r_glsl.integer && gl_support_fragment_shader)
3490 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3491 else if (gl_combine.integer && r_textureunits.integer >= 2)
3492 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3494 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3497 GL_LockArrays(0, 0);
3500 #define BATCHSIZE 256
3501 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3503 int surfacelistindex;
3506 msurface_t *texturesurfacelist[BATCHSIZE];
3507 // if the model is static it doesn't matter what value we give for
3508 // wantnormals and wanttangents, so this logic uses only rules applicable
3509 // to a model, knowing that they are meaningless otherwise
3510 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3511 RSurf_ActiveEntity(ent, false, false);
3513 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3516 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3518 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3520 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3523 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
3524 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3526 t = surface->texture;
3527 rsurface_lightmaptexture = surface->lightmaptexture;
3528 R_UpdateTextureInfo(ent, t);
3529 rsurface_texture = t->currentframe;
3532 texturesurfacelist[batchcount++] = surface;
3535 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
3536 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3540 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3542 int texturesurfaceindex;
3543 vec3_t tempcenter, center;
3544 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3546 // drawing sky transparently would be too difficult
3547 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3549 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3551 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3552 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3553 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3554 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3555 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3556 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);
3561 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3564 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3565 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3567 int i, j, f, flagsmask;
3568 int counttriangles = 0;
3570 model_t *model = ent->model;
3571 const int maxsurfacelist = 1024;
3572 int numsurfacelist = 0;
3573 msurface_t *surfacelist[1024];
3577 // if the model is static it doesn't matter what value we give for
3578 // wantnormals and wanttangents, so this logic uses only rules applicable
3579 // to a model, knowing that they are meaningless otherwise
3580 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3581 RSurf_ActiveEntity(ent, false, false);
3583 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3585 // update light styles
3586 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3588 msurface_t *surface, **surfacechain;
3589 for (i = 0;i < model->brushq1.light_styles;i++)
3591 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3593 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3594 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3595 for (;(surface = *surfacechain);surfacechain++)
3596 surface->cached_dlight = true;
3601 R_UpdateAllTextureInfo(ent);
3602 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3605 rsurface_lightmaptexture = NULL;
3606 rsurface_texture = NULL;
3608 if (ent == r_refdef.worldentity)
3610 msurface_t *surface;
3611 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3613 if (!r_viewcache.world_surfacevisible[j])
3615 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3619 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3622 t = surface->texture;
3623 rsurface_lightmaptexture = surface->lightmaptexture;
3624 rsurface_texture = t->currentframe;
3625 f = rsurface_texture->currentmaterialflags & flagsmask;
3627 if (f && surface->num_triangles)
3629 // if lightmap parameters changed, rebuild lightmap texture
3630 if (surface->cached_dlight)
3631 R_BuildLightMap(ent, surface);
3632 // add face to draw list
3633 surfacelist[numsurfacelist++] = surface;
3634 counttriangles += surface->num_triangles;
3635 if (numsurfacelist >= maxsurfacelist)
3637 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3645 msurface_t *surface;
3646 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3648 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3652 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3655 t = surface->texture;
3656 rsurface_lightmaptexture = surface->lightmaptexture;
3657 rsurface_texture = t->currentframe;
3658 f = rsurface_texture->currentmaterialflags & flagsmask;
3660 if (f && surface->num_triangles)
3662 // if lightmap parameters changed, rebuild lightmap texture
3663 if (surface->cached_dlight)
3664 R_BuildLightMap(ent, surface);
3665 // add face to draw list
3666 surfacelist[numsurfacelist++] = surface;
3667 counttriangles += surface->num_triangles;
3668 if (numsurfacelist >= maxsurfacelist)
3670 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3677 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3678 r_refdef.stats.entities_triangles += counttriangles;
3681 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3684 const msurface_t *surface;
3687 R_Mesh_Matrix(&ent->matrix);
3688 R_Mesh_ColorPointer(NULL);
3689 R_Mesh_ResetTextureState();
3690 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3691 GL_DepthMask(false);
3692 GL_DepthTest(!r_showdisabledepthtest.integer);
3693 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3694 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3695 if (brush->colbrushf && brush->colbrushf->numtriangles)
3696 R_DrawCollisionBrush(brush->colbrushf);
3697 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3698 if (surface->num_collisiontriangles)
3699 R_DrawCollisionSurface(ent, surface);
3700 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3703 if (r_showtris.integer || r_shownormals.integer)
3706 msurface_t *surface;
3707 const int *elements;
3710 GL_DepthTest(!r_showdisabledepthtest.integer);
3712 GL_BlendFunc(GL_ONE, GL_ZERO);
3713 R_Mesh_ColorPointer(NULL);
3714 R_Mesh_ResetTextureState();
3715 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3717 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3719 rsurface_texture = surface->texture->currentframe;
3720 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3722 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3723 if (r_showtris.integer)
3725 if (!rsurface_texture->currentlayers->depthmask)
3726 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
3727 else if (ent == r_refdef.worldentity)
3728 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
3730 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
3731 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3734 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3736 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3737 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3738 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3743 if (r_shownormals.integer)
3745 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
3747 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3749 VectorCopy(rsurface_vertex3f + l * 3, v);
3750 qglVertex3f(v[0], v[1], v[2]);
3751 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3752 qglVertex3f(v[0], v[1], v[2]);
3756 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
3758 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3760 VectorCopy(rsurface_vertex3f + l * 3, v);
3761 qglVertex3f(v[0], v[1], v[2]);
3762 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3763 qglVertex3f(v[0], v[1], v[2]);
3767 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
3769 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3771 VectorCopy(rsurface_vertex3f + l * 3, v);
3772 qglVertex3f(v[0], v[1], v[2]);
3773 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3774 qglVertex3f(v[0], v[1], v[2]);
3781 rsurface_texture = NULL;