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_ResetViewRendering(void)
1413 if (gl_support_fragment_shader)
1415 qglUseProgramObjectARB(0);CHECKGLERROR
1418 // GL is weird because it's bottom to top, r_view.y is top to bottom
1419 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
1420 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
1421 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
1422 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
1423 GL_ScissorTest(false);
1424 GL_DepthMask(false);
1425 GL_DepthTest(false);
1426 R_Mesh_Matrix(&identitymatrix);
1427 R_Mesh_ResetTextureState();
1431 R_Bloom_SetupShader(
1433 "// written by Forest 'LordHavoc' Hale\n"
1435 "// common definitions between vertex shader and fragment shader:\n"
1437 "#ifdef __GLSL_CG_DATA_TYPES\n"
1438 "#define myhalf half\n"
1439 "#define myhvec2 hvec2\n"
1440 "#define myhvec3 hvec3\n"
1441 "#define myhvec4 hvec4\n"
1443 "#define myhalf float\n"
1444 "#define myhvec2 vec2\n"
1445 "#define myhvec3 vec3\n"
1446 "#define myhvec4 vec4\n"
1449 "varying vec2 ScreenTexCoord;\n"
1450 "varying vec2 BloomTexCoord;\n"
1455 "// vertex shader specific:\n"
1456 "#ifdef VERTEX_SHADER\n"
1460 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
1461 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
1462 " // transform vertex to camera space, using ftransform to match non-VS\n"
1464 " gl_Position = ftransform();\n"
1467 "#endif // VERTEX_SHADER\n"
1472 "// fragment shader specific:\n"
1473 "#ifdef FRAGMENT_SHADER\n"
1478 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
1479 " for (x = -BLUR_X;x <= BLUR_X;x++)
1480 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1481 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1482 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1483 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
1485 " gl_FragColor = vec4(color);\n"
1488 "#endif // FRAGMENT_SHADER\n"
1491 void R_SetupView(const matrix4x4_t *matrix)
1493 if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
1494 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
1496 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
1498 GL_SetupView_Orientation_FromEntity(matrix);
1501 void R_RenderScene(void);
1503 void R_Bloom_StartFrame(void)
1505 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
1507 // set bloomwidth and bloomheight to the bloom resolution that will be
1508 // used (often less than the screen resolution for faster rendering)
1509 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_view.width);
1510 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
1511 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
1513 // calculate desired texture sizes
1514 if (gl_support_arb_texture_non_power_of_two)
1516 screentexturewidth = r_view.width;
1517 screentextureheight = r_view.height;
1518 bloomtexturewidth = r_bloomstate.bloomwidth;
1519 bloomtextureheight = r_bloomstate.bloomheight;
1523 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
1524 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
1525 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
1526 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
1531 screentexturewidth = screentextureheight = 0;
1533 else if (r_bloom.integer)
1538 screentexturewidth = screentextureheight = 0;
1539 bloomtexturewidth = bloomtextureheight = 0;
1542 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)
1544 // can't use bloom if the parameters are too weird
1545 // can't use bloom if the card does not support the texture size
1546 if (r_bloomstate.texture_screen)
1547 R_FreeTexture(r_bloomstate.texture_screen);
1548 if (r_bloomstate.texture_bloom)
1549 R_FreeTexture(r_bloomstate.texture_bloom);
1550 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1554 r_bloomstate.enabled = true;
1555 r_bloomstate.hdr = r_hdr.integer != 0;
1557 // allocate textures as needed
1558 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
1560 if (r_bloomstate.texture_screen)
1561 R_FreeTexture(r_bloomstate.texture_screen);
1562 r_bloomstate.texture_screen = NULL;
1563 r_bloomstate.screentexturewidth = screentexturewidth;
1564 r_bloomstate.screentextureheight = screentextureheight;
1565 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
1566 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);
1568 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
1570 if (r_bloomstate.texture_bloom)
1571 R_FreeTexture(r_bloomstate.texture_bloom);
1572 r_bloomstate.texture_bloom = NULL;
1573 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
1574 r_bloomstate.bloomtextureheight = bloomtextureheight;
1575 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
1576 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);
1579 // set up a texcoord array for the full resolution screen image
1580 // (we have to keep this around to copy back during final render)
1581 r_bloomstate.screentexcoord2f[0] = 0;
1582 r_bloomstate.screentexcoord2f[1] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1583 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1584 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
1585 r_bloomstate.screentexcoord2f[4] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
1586 r_bloomstate.screentexcoord2f[5] = 0;
1587 r_bloomstate.screentexcoord2f[6] = 0;
1588 r_bloomstate.screentexcoord2f[7] = 0;
1590 // set up a texcoord array for the reduced resolution bloom image
1591 // (which will be additive blended over the screen image)
1592 r_bloomstate.bloomtexcoord2f[0] = 0;
1593 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1594 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1595 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1596 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1597 r_bloomstate.bloomtexcoord2f[5] = 0;
1598 r_bloomstate.bloomtexcoord2f[6] = 0;
1599 r_bloomstate.bloomtexcoord2f[7] = 0;
1602 void R_Bloom_CopyScreenTexture(float colorscale)
1604 r_refdef.stats.bloom++;
1606 R_ResetViewRendering();
1607 R_Mesh_VertexPointer(r_screenvertex3f);
1608 R_Mesh_ColorPointer(NULL);
1609 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1610 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1612 // copy view into the screen texture
1613 GL_ActiveTexture(0);
1615 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
1616 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1618 // now scale it down to the bloom texture size
1620 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1621 GL_BlendFunc(GL_ONE, GL_ZERO);
1622 GL_Color(colorscale, colorscale, colorscale, 1);
1623 // TODO: optimize with multitexture or GLSL
1624 R_Mesh_Draw(0, 4, 2, polygonelements);
1625 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1627 // we now have a bloom image in the framebuffer
1628 // copy it into the bloom image texture for later processing
1629 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1630 GL_ActiveTexture(0);
1632 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
1633 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1636 void R_Bloom_CopyHDRTexture(void)
1638 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1639 GL_ActiveTexture(0);
1641 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
1642 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
1645 void R_Bloom_MakeTexture(void)
1648 float xoffset, yoffset, r;
1650 r_refdef.stats.bloom++;
1652 R_ResetViewRendering();
1653 R_Mesh_VertexPointer(r_screenvertex3f);
1654 R_Mesh_ColorPointer(NULL);
1656 // we have a bloom image in the framebuffer
1658 qglViewport(r_view.x, vid.height - (r_view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
1660 for (x = 1;x < r_bloom_colorexponent.value;)
1663 r = bound(0, r_bloom_colorexponent.value / x, 1);
1664 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1665 GL_Color(r, r, r, 1);
1666 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1667 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1668 R_Mesh_Draw(0, 4, 2, polygonelements);
1669 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1671 // copy the vertically blurred bloom view to a texture
1672 GL_ActiveTexture(0);
1674 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
1675 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1678 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
1679 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1680 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f);
1682 for (dir = 0;dir < 2;dir++)
1684 // blend on at multiple vertical offsets to achieve a vertical blur
1685 // TODO: do offset blends using GLSL
1686 GL_BlendFunc(GL_ONE, GL_ZERO);
1687 for (x = -range;x <= range;x++)
1689 if (!dir){xoffset = 0;yoffset = x;}
1690 else {xoffset = x;yoffset = 0;}
1691 xoffset /= (float)r_bloomstate.bloomtexturewidth;
1692 yoffset /= (float)r_bloomstate.bloomtextureheight;
1693 // compute a texcoord array with the specified x and y offset
1694 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
1695 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1696 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1697 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
1698 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
1699 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
1700 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
1701 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
1702 // this r value looks like a 'dot' particle, fading sharply to
1703 // black at the edges
1704 // (probably not realistic but looks good enough)
1705 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
1706 //r = (dir ? 1.0f : r_bloom_brighten.value)/(range*2+1);
1707 r = (dir ? 1.0f : r_bloom_brighten.value)/(range*2+1)*(1 - x*x/(float)(range*range));
1708 GL_Color(r, r, r, 1);
1709 R_Mesh_Draw(0, 4, 2, polygonelements);
1710 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1711 GL_BlendFunc(GL_ONE, GL_ONE);
1714 // copy the vertically blurred bloom view to a texture
1715 GL_ActiveTexture(0);
1717 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
1718 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1721 // apply subtract last
1722 // (just like it would be in a GLSL shader)
1723 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
1725 GL_BlendFunc(GL_ONE, GL_ZERO);
1726 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1727 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1728 GL_Color(1, 1, 1, 1);
1729 R_Mesh_Draw(0, 4, 2, polygonelements);
1730 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1732 GL_BlendFunc(GL_ONE, GL_ONE);
1733 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
1734 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1735 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1736 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
1737 R_Mesh_Draw(0, 4, 2, polygonelements);
1738 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1739 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
1741 // copy the darkened bloom view to a texture
1742 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1743 GL_ActiveTexture(0);
1745 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
1746 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
1750 void R_HDR_RenderBloomTexture(void)
1752 int oldwidth, oldheight;
1754 oldwidth = r_view.width;
1755 oldheight = r_view.height;
1756 r_view.width = r_bloomstate.bloomwidth;
1757 r_view.height = r_bloomstate.bloomheight;
1759 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
1760 // TODO: add exposure compensation features
1762 r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
1765 R_ResetViewRendering();
1767 R_Bloom_CopyHDRTexture();
1768 R_Bloom_MakeTexture();
1770 R_ResetViewRendering();
1771 GL_ScissorTest(true);
1775 if (r_timereport_active)
1776 R_TimeReport("clear");
1778 // restore the view settings
1779 r_view.width = oldwidth;
1780 r_view.height = oldheight;
1783 static void R_BlendView(void)
1785 if (r_bloomstate.enabled && r_bloomstate.hdr)
1787 // render high dynamic range bloom effect
1788 // the bloom texture was made earlier this render, so we just need to
1789 // blend it onto the screen...
1790 R_ResetViewRendering();
1791 R_Mesh_VertexPointer(r_screenvertex3f);
1792 R_Mesh_ColorPointer(NULL);
1793 GL_Color(1, 1, 1, 1);
1794 GL_BlendFunc(GL_ONE, GL_ONE);
1795 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1796 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1797 R_Mesh_Draw(0, 4, 2, polygonelements);
1798 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1800 else if (r_bloomstate.enabled)
1802 // render simple bloom effect
1803 // copy the screen and shrink it and darken it for the bloom process
1804 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
1805 // make the bloom texture
1806 R_Bloom_MakeTexture();
1807 // put the original screen image back in place and blend the bloom
1809 R_ResetViewRendering();
1810 R_Mesh_VertexPointer(r_screenvertex3f);
1811 R_Mesh_ColorPointer(NULL);
1812 GL_Color(1, 1, 1, 1);
1813 GL_BlendFunc(GL_ONE, GL_ZERO);
1814 // do both in one pass if possible
1815 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
1816 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f);
1817 if (r_textureunits.integer >= 2 && gl_combine.integer)
1819 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
1820 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
1821 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f);
1825 R_Mesh_Draw(0, 4, 2, polygonelements);
1826 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1827 // now blend on the bloom texture
1828 GL_BlendFunc(GL_ONE, GL_ONE);
1829 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
1830 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
1832 R_Mesh_Draw(0, 4, 2, polygonelements);
1833 r_refdef.stats.bloom_drawpixels += r_view.width * r_view.height;
1835 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
1837 // apply a color tint to the whole view
1838 R_ResetViewRendering();
1839 R_Mesh_VertexPointer(r_screenvertex3f);
1840 R_Mesh_ColorPointer(NULL);
1841 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1842 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1843 R_Mesh_Draw(0, 4, 2, polygonelements);
1847 void R_RenderScene(void);
1849 matrix4x4_t r_waterscrollmatrix;
1851 void R_UpdateVariables(void)
1855 r_refdef.farclip = 4096;
1856 if (r_refdef.worldmodel)
1857 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
1858 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
1860 r_refdef.polygonfactor = 0;
1861 r_refdef.polygonoffset = 0;
1862 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_shadow_polygonfactor.value;
1863 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_shadow_polygonoffset.value;
1865 r_refdef.rtworld = r_shadow_realtime_world.integer;
1866 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1867 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1868 r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1869 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1870 if (r_showsurfaces.integer)
1872 r_refdef.rtworld = false;
1873 r_refdef.rtworldshadows = false;
1874 r_refdef.rtdlight = false;
1875 r_refdef.rtdlightshadows = false;
1876 r_refdef.lightmapintensity = 0;
1879 if (gamemode == GAME_NEHAHRA)
1881 if (gl_fogenable.integer)
1883 r_refdef.oldgl_fogenable = true;
1884 r_refdef.fog_density = gl_fogdensity.value;
1885 r_refdef.fog_red = gl_fogred.value;
1886 r_refdef.fog_green = gl_foggreen.value;
1887 r_refdef.fog_blue = gl_fogblue.value;
1889 else if (r_refdef.oldgl_fogenable)
1891 r_refdef.oldgl_fogenable = false;
1892 r_refdef.fog_density = 0;
1893 r_refdef.fog_red = 0;
1894 r_refdef.fog_green = 0;
1895 r_refdef.fog_blue = 0;
1898 if (r_refdef.fog_density)
1900 r_refdef.fogcolor[0] = bound(0.0f, r_refdef.fog_red , 1.0f);
1901 r_refdef.fogcolor[1] = bound(0.0f, r_refdef.fog_green, 1.0f);
1902 r_refdef.fogcolor[2] = bound(0.0f, r_refdef.fog_blue , 1.0f);
1904 if (r_refdef.fog_density)
1906 r_refdef.fogenabled = true;
1907 // this is the point where the fog reaches 0.9986 alpha, which we
1908 // consider a good enough cutoff point for the texture
1909 // (0.9986 * 256 == 255.6)
1910 r_refdef.fogrange = 400 / r_refdef.fog_density;
1911 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
1912 r_refdef.fogtabledistmultiplier = FOGTABLEWIDTH * r_refdef.fograngerecip;
1913 // fog color was already set
1916 r_refdef.fogenabled = false;
1924 void R_RenderView(void)
1926 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1927 return; //Host_Error ("R_RenderView: NULL worldmodel");
1930 if (r_timereport_active)
1931 R_TimeReport("setup");
1934 if (r_timereport_active)
1935 R_TimeReport("visibility");
1937 R_ResetViewRendering();
1938 GL_ScissorTest(true);
1942 if (r_timereport_active)
1943 R_TimeReport("clear");
1945 R_Bloom_StartFrame();
1947 // this produces a bloom texture to be used in R_BlendView() later
1949 R_HDR_RenderBloomTexture();
1951 r_view.colorscale = r_hdr_scenebrightness.value;
1955 if (r_timereport_active)
1956 R_TimeReport("blendview");
1958 GL_Scissor(0, 0, vid.width, vid.height);
1959 GL_ScissorTest(false);
1963 extern void R_DrawLightningBeams (void);
1964 extern void VM_AddPolygonsToMeshQueue (void);
1965 extern void R_DrawPortals (void);
1966 void R_RenderScene(void)
1970 // don't let sound skip if going slow
1971 if (r_refdef.extraupdate)
1975 if (gl_support_fragment_shader)
1977 qglUseProgramObjectARB(0);CHECKGLERROR
1979 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1980 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
1981 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
1983 R_ResetViewRendering();
1984 R_SetupView(&r_view.matrix);
1986 R_MeshQueue_BeginScene();
1988 R_Shadow_UpdateWorldLightSelection();
1992 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);
1994 if (cl.csqc_vidvars.drawworld)
1996 // don't let sound skip if going slow
1997 if (r_refdef.extraupdate)
2000 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
2002 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
2003 if (r_timereport_active)
2004 R_TimeReport("worldsky");
2007 if (R_DrawBrushModelsSky() && r_timereport_active)
2008 R_TimeReport("bmodelsky");
2010 if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
2012 r_refdef.worldmodel->Draw(r_refdef.worldentity);
2013 if (r_timereport_active)
2014 R_TimeReport("world");
2018 // don't let sound skip if going slow
2019 if (r_refdef.extraupdate)
2023 if (r_timereport_active)
2024 R_TimeReport("models");
2026 // don't let sound skip if going slow
2027 if (r_refdef.extraupdate)
2030 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
2032 R_DrawModelShadows();
2034 // don't let sound skip if going slow
2035 if (r_refdef.extraupdate)
2039 R_ShadowVolumeLighting(false);
2040 if (r_timereport_active)
2041 R_TimeReport("rtlights");
2043 // don't let sound skip if going slow
2044 if (r_refdef.extraupdate)
2047 if (cl.csqc_vidvars.drawworld)
2049 R_DrawLightningBeams();
2050 if (r_timereport_active)
2051 R_TimeReport("lightning");
2054 if (r_timereport_active)
2055 R_TimeReport("particles");
2058 if (r_timereport_active)
2059 R_TimeReport("explosions");
2062 if (gl_support_fragment_shader)
2064 qglUseProgramObjectARB(0);CHECKGLERROR
2066 VM_AddPolygonsToMeshQueue();
2068 if (r_drawportals.integer)
2071 if (r_timereport_active)
2072 R_TimeReport("portals");
2075 if (gl_support_fragment_shader)
2077 qglUseProgramObjectARB(0);CHECKGLERROR
2079 R_MeshQueue_RenderTransparent();
2080 if (r_timereport_active)
2081 R_TimeReport("drawtrans");
2083 if (gl_support_fragment_shader)
2085 qglUseProgramObjectARB(0);CHECKGLERROR
2088 if (cl.csqc_vidvars.drawworld)
2091 if (r_timereport_active)
2092 R_TimeReport("coronas");
2095 // don't let sound skip if going slow
2096 if (r_refdef.extraupdate)
2100 if (gl_support_fragment_shader)
2102 qglUseProgramObjectARB(0);CHECKGLERROR
2104 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
2105 qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2109 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
2112 float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
2113 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2114 GL_DepthMask(false);
2116 R_Mesh_Matrix(&identitymatrix);
2118 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
2119 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
2120 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
2121 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
2122 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
2123 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
2124 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
2125 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
2126 R_FillColors(color, 8, cr, cg, cb, ca);
2127 if (r_refdef.fogenabled)
2129 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
2131 f2 = VERTEXFOGTABLE(VectorDistance(v, r_view.origin));
2133 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
2134 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
2135 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
2138 R_Mesh_VertexPointer(vertex3f);
2139 R_Mesh_ColorPointer(color);
2140 R_Mesh_ResetTextureState();
2145 int nomodelelements[24] =
2157 float nomodelvertex3f[6*3] =
2167 float nomodelcolor4f[6*4] =
2169 0.0f, 0.0f, 0.5f, 1.0f,
2170 0.0f, 0.0f, 0.5f, 1.0f,
2171 0.0f, 0.5f, 0.0f, 1.0f,
2172 0.0f, 0.5f, 0.0f, 1.0f,
2173 0.5f, 0.0f, 0.0f, 1.0f,
2174 0.5f, 0.0f, 0.0f, 1.0f
2177 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
2182 // this is only called once per entity so numsurfaces is always 1, and
2183 // surfacelist is always {0}, so this code does not handle batches
2184 R_Mesh_Matrix(&ent->matrix);
2186 if (ent->flags & EF_ADDITIVE)
2188 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2189 GL_DepthMask(false);
2191 else if (ent->alpha < 1)
2193 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2194 GL_DepthMask(false);
2198 GL_BlendFunc(GL_ONE, GL_ZERO);
2201 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
2202 R_Mesh_VertexPointer(nomodelvertex3f);
2203 if (r_refdef.fogenabled)
2206 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2207 R_Mesh_ColorPointer(color4f);
2208 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2209 f2 = VERTEXFOGTABLE(VectorDistance(org, r_view.origin));
2211 for (i = 0, c = color4f;i < 6;i++, c += 4)
2213 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
2214 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
2215 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
2219 else if (ent->alpha != 1)
2221 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
2222 R_Mesh_ColorPointer(color4f);
2223 for (i = 0, c = color4f;i < 6;i++, c += 4)
2227 R_Mesh_ColorPointer(nomodelcolor4f);
2228 R_Mesh_ResetTextureState();
2229 R_Mesh_Draw(0, 6, 8, nomodelelements);
2232 void R_DrawNoModel(entity_render_t *ent)
2235 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
2236 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
2237 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, r_shadow_rtlight);
2239 // R_DrawNoModelCallback(ent, 0);
2242 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
2244 vec3_t right1, right2, diff, normal;
2246 VectorSubtract (org2, org1, normal);
2248 // calculate 'right' vector for start
2249 VectorSubtract (r_view.origin, org1, diff);
2250 CrossProduct (normal, diff, right1);
2251 VectorNormalize (right1);
2253 // calculate 'right' vector for end
2254 VectorSubtract (r_view.origin, org2, diff);
2255 CrossProduct (normal, diff, right2);
2256 VectorNormalize (right2);
2258 vert[ 0] = org1[0] + width * right1[0];
2259 vert[ 1] = org1[1] + width * right1[1];
2260 vert[ 2] = org1[2] + width * right1[2];
2261 vert[ 3] = org1[0] - width * right1[0];
2262 vert[ 4] = org1[1] - width * right1[1];
2263 vert[ 5] = org1[2] - width * right1[2];
2264 vert[ 6] = org2[0] - width * right2[0];
2265 vert[ 7] = org2[1] - width * right2[1];
2266 vert[ 8] = org2[2] - width * right2[2];
2267 vert[ 9] = org2[0] + width * right2[0];
2268 vert[10] = org2[1] + width * right2[1];
2269 vert[11] = org2[2] + width * right2[2];
2272 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
2274 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)
2276 float fog = 0.0f, ifog;
2279 if (r_refdef.fogenabled)
2280 fog = VERTEXFOGTABLE(VectorDistance(origin, r_view.origin));
2283 R_Mesh_Matrix(&identitymatrix);
2284 GL_BlendFunc(blendfunc1, blendfunc2);
2285 GL_DepthMask(false);
2286 GL_DepthTest(!depthdisable);
2288 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
2289 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
2290 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
2291 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
2292 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
2293 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
2294 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
2295 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
2296 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
2297 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
2298 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
2299 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
2301 R_Mesh_VertexPointer(vertex3f);
2302 R_Mesh_ColorPointer(NULL);
2303 R_Mesh_ResetTextureState();
2304 R_Mesh_TexBind(0, R_GetTexture(texture));
2305 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f);
2306 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
2307 GL_Color(cr * ifog * r_view.colorscale, cg * ifog * r_view.colorscale, cb * ifog * r_view.colorscale, ca);
2308 R_Mesh_Draw(0, 4, 2, polygonelements);
2310 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
2312 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
2313 GL_BlendFunc(blendfunc1, GL_ONE);
2314 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);
2315 R_Mesh_Draw(0, 4, 2, polygonelements);
2319 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
2324 VectorSet(v, x, y, z);
2325 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
2326 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
2328 if (i == mesh->numvertices)
2330 if (mesh->numvertices < mesh->maxvertices)
2332 VectorCopy(v, vertex3f);
2333 mesh->numvertices++;
2335 return mesh->numvertices;
2341 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
2345 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2346 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
2347 e = mesh->element3i + mesh->numtriangles * 3;
2348 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
2350 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
2351 if (mesh->numtriangles < mesh->maxtriangles)
2356 mesh->numtriangles++;
2358 element[1] = element[2];
2362 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
2366 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2367 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
2368 e = mesh->element3i + mesh->numtriangles * 3;
2369 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
2371 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
2372 if (mesh->numtriangles < mesh->maxtriangles)
2377 mesh->numtriangles++;
2379 element[1] = element[2];
2383 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
2384 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
2386 int planenum, planenum2;
2389 mplane_t *plane, *plane2;
2391 double temppoints[2][256*3];
2392 // figure out how large a bounding box we need to properly compute this brush
2394 for (w = 0;w < numplanes;w++)
2395 maxdist = max(maxdist, planes[w].dist);
2396 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
2397 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
2398 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
2402 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
2403 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
2405 if (planenum2 == planenum)
2407 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);
2410 if (tempnumpoints < 3)
2412 // generate elements forming a triangle fan for this polygon
2413 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
2417 static void R_DrawCollisionBrush(const colbrushf_t *brush)
2420 R_Mesh_VertexPointer(brush->points->v);
2421 i = (int)(((size_t)brush) / sizeof(colbrushf_t));
2422 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);
2423 GL_LockArrays(0, brush->numpoints);
2424 R_Mesh_Draw(0, brush->numpoints, brush->numtriangles, brush->elements);
2425 GL_LockArrays(0, 0);
2428 static void R_DrawCollisionSurface(const entity_render_t *ent, const msurface_t *surface)
2431 if (!surface->num_collisiontriangles)
2433 R_Mesh_VertexPointer(surface->data_collisionvertex3f);
2434 i = (int)(((size_t)surface) / sizeof(msurface_t));
2435 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);
2436 GL_LockArrays(0, surface->num_collisionvertices);
2437 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i);
2438 GL_LockArrays(0, 0);
2441 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)
2443 texturelayer_t *layer;
2444 layer = t->currentlayers + t->currentnumlayers++;
2446 layer->depthmask = depthmask;
2447 layer->blendfunc1 = blendfunc1;
2448 layer->blendfunc2 = blendfunc2;
2449 layer->texture = texture;
2450 layer->texmatrix = *matrix;
2451 layer->color[0] = r * r_view.colorscale;
2452 layer->color[1] = g * r_view.colorscale;
2453 layer->color[2] = b * r_view.colorscale;
2454 layer->color[3] = a;
2457 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
2459 // FIXME: identify models using a better check than ent->model->brush.shadowmesh
2460 //int lightmode = ((ent->effects & EF_FULLBRIGHT) || ent->model->brush.shadowmesh) ? 0 : 2;
2462 // switch to an alternate material if this is a q1bsp animated material
2464 texture_t *texture = t;
2465 model_t *model = ent->model;
2466 int s = ent->skinnum;
2467 if ((unsigned int)s >= (unsigned int)model->numskins)
2469 if (model->skinscenes)
2471 if (model->skinscenes[s].framecount > 1)
2472 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
2474 s = model->skinscenes[s].firstframe;
2477 t = t + s * model->num_surfaces;
2480 // use an alternate animation if the entity's frame is not 0,
2481 // and only if the texture has an alternate animation
2482 if (ent->frame != 0 && t->anim_total[1])
2483 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
2485 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
2487 texture->currentframe = t;
2490 // pick a new currentskinframe if the material is animated
2491 if (t->numskinframes >= 2)
2492 t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
2494 t->currentmaterialflags = t->basematerialflags;
2495 t->currentalpha = ent->alpha;
2496 if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
2497 t->currentalpha *= r_wateralpha.value;
2498 if (!(ent->flags & RENDER_LIGHT))
2499 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
2500 if (ent->effects & EF_ADDITIVE)
2501 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2502 else if (t->currentalpha < 1)
2503 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT;
2504 if (ent->effects & EF_NODEPTHTEST)
2505 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
2506 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
2507 t->currenttexmatrix = r_waterscrollmatrix;
2509 t->currenttexmatrix = identitymatrix;
2511 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
2512 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2513 t->glosstexture = r_texture_white;
2514 t->specularpower = r_shadow_glossexponent.value;
2515 t->specularscale = 0;
2516 if (r_shadow_gloss.integer > 0)
2518 if (t->currentskinframe->gloss)
2520 if (r_shadow_glossintensity.value > 0)
2522 t->glosstexture = t->currentskinframe->gloss;
2523 t->specularscale = r_shadow_glossintensity.value;
2526 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
2527 t->specularscale = r_shadow_gloss2intensity.value;
2530 t->currentnumlayers = 0;
2531 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
2533 if (gl_lightmaps.integer)
2534 R_Texture_AddLayer(t, true, GL_ONE, GL_ZERO, TEXTURELAYERTYPE_LITTEXTURE, r_texture_white, &identitymatrix, 1, 1, 1, 1);
2535 else if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
2537 int blendfunc1, blendfunc2, depthmask;
2538 if (t->currentmaterialflags & MATERIALFLAG_ADD)
2540 blendfunc1 = GL_SRC_ALPHA;
2541 blendfunc2 = GL_ONE;
2543 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
2545 blendfunc1 = GL_SRC_ALPHA;
2546 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
2548 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
2550 blendfunc1 = t->customblendfunc[0];
2551 blendfunc2 = t->customblendfunc[1];
2555 blendfunc1 = GL_ONE;
2556 blendfunc2 = GL_ZERO;
2558 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
2559 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
2561 rtexture_t *currentbasetexture;
2563 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
2564 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
2565 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
2566 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2568 // fullbright is not affected by r_refdef.lightmapintensity
2569 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
2570 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2571 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);
2572 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2573 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);
2579 // q3bsp has no lightmap updates, so the lightstylevalue that
2580 // would normally be baked into the lightmap must be
2581 // applied to the color
2582 if (ent->model->type == mod_brushq3)
2583 colorscale *= r_refdef.lightstylevalue[0] * (1.0f / 256.0f);
2584 colorscale *= r_refdef.lightmapintensity;
2585 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);
2586 if (r_ambient.value >= (1.0f/64.0f))
2587 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);
2588 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
2590 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);
2591 if (r_ambient.value >= (1.0f/64.0f))
2592 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);
2594 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
2596 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);
2597 if (r_ambient.value >= (1.0f/64.0f))
2598 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);
2601 if (t->currentskinframe->glow != NULL)
2602 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);
2603 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
2605 // if this is opaque use alpha blend which will darken the earlier
2608 // if this is an alpha blended material, all the earlier passes
2609 // were darkened by fog already, so we only need to add the fog
2610 // color ontop through the fog mask texture
2612 // if this is an additive blended material, all the earlier passes
2613 // were darkened by fog already, and we should not add fog color
2614 // (because the background was not darkened, there is no fog color
2615 // that was lost behind it).
2616 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);
2623 void R_UpdateAllTextureInfo(entity_render_t *ent)
2627 for (i = 0;i < ent->model->num_textures;i++)
2628 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
2631 int rsurface_array_size = 0;
2632 float *rsurface_array_modelvertex3f = NULL;
2633 float *rsurface_array_modelsvector3f = NULL;
2634 float *rsurface_array_modeltvector3f = NULL;
2635 float *rsurface_array_modelnormal3f = NULL;
2636 float *rsurface_array_deformedvertex3f = NULL;
2637 float *rsurface_array_deformedsvector3f = NULL;
2638 float *rsurface_array_deformedtvector3f = NULL;
2639 float *rsurface_array_deformednormal3f = NULL;
2640 float *rsurface_array_color4f = NULL;
2641 float *rsurface_array_texcoord3f = NULL;
2643 void R_Mesh_ResizeArrays(int newvertices)
2646 if (rsurface_array_size >= newvertices)
2648 if (rsurface_array_modelvertex3f)
2649 Mem_Free(rsurface_array_modelvertex3f);
2650 rsurface_array_size = (newvertices + 1023) & ~1023;
2651 base = (float *)Mem_Alloc(r_main_mempool, rsurface_array_size * sizeof(float[31]));
2652 rsurface_array_modelvertex3f = base + rsurface_array_size * 0;
2653 rsurface_array_modelsvector3f = base + rsurface_array_size * 3;
2654 rsurface_array_modeltvector3f = base + rsurface_array_size * 6;
2655 rsurface_array_modelnormal3f = base + rsurface_array_size * 9;
2656 rsurface_array_deformedvertex3f = base + rsurface_array_size * 12;
2657 rsurface_array_deformedsvector3f = base + rsurface_array_size * 15;
2658 rsurface_array_deformedtvector3f = base + rsurface_array_size * 18;
2659 rsurface_array_deformednormal3f = base + rsurface_array_size * 21;
2660 rsurface_array_texcoord3f = base + rsurface_array_size * 24;
2661 rsurface_array_color4f = base + rsurface_array_size * 27;
2664 float *rsurface_modelvertex3f;
2665 float *rsurface_modelsvector3f;
2666 float *rsurface_modeltvector3f;
2667 float *rsurface_modelnormal3f;
2668 float *rsurface_vertex3f;
2669 float *rsurface_svector3f;
2670 float *rsurface_tvector3f;
2671 float *rsurface_normal3f;
2672 float *rsurface_lightmapcolor4f;
2673 vec3_t rsurface_modelorg;
2674 qboolean rsurface_generatedvertex;
2675 const entity_render_t *rsurface_entity;
2676 const model_t *rsurface_model;
2677 texture_t *rsurface_texture;
2678 rtexture_t *rsurface_lightmaptexture;
2679 rsurfmode_t rsurface_mode;
2680 texture_t *rsurface_glsl_texture;
2681 qboolean rsurface_glsl_uselightmap;
2683 void RSurf_CleanUp(void)
2686 if (rsurface_mode == RSURFMODE_GLSL)
2688 qglUseProgramObjectARB(0);CHECKGLERROR
2690 GL_AlphaTest(false);
2691 rsurface_mode = RSURFMODE_NONE;
2692 rsurface_lightmaptexture = NULL;
2693 rsurface_texture = NULL;
2694 rsurface_glsl_texture = NULL;
2695 rsurface_glsl_uselightmap = false;
2698 void RSurf_ActiveEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
2701 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2702 rsurface_entity = ent;
2703 rsurface_model = ent->model;
2704 if (rsurface_array_size < rsurface_model->surfmesh.num_vertices)
2705 R_Mesh_ResizeArrays(rsurface_model->surfmesh.num_vertices);
2706 R_Mesh_Matrix(&ent->matrix);
2707 Matrix4x4_Transform(&ent->inversematrix, r_view.origin, rsurface_modelorg);
2708 if ((rsurface_entity->frameblend[0].lerp != 1 || rsurface_entity->frameblend[0].frame != 0) && rsurface_model->surfmesh.isanimated)
2712 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2713 rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2714 rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2715 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2716 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, rsurface_array_modelsvector3f, rsurface_array_modeltvector3f);
2718 else if (wantnormals)
2720 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2721 rsurface_modelsvector3f = NULL;
2722 rsurface_modeltvector3f = NULL;
2723 rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2724 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, rsurface_array_modelnormal3f, NULL, NULL);
2728 rsurface_modelvertex3f = rsurface_array_modelvertex3f;
2729 rsurface_modelsvector3f = NULL;
2730 rsurface_modeltvector3f = NULL;
2731 rsurface_modelnormal3f = NULL;
2732 Mod_Alias_GetMesh_Vertices(rsurface_model, rsurface_entity->frameblend, rsurface_array_modelvertex3f, NULL, NULL, NULL);
2734 rsurface_generatedvertex = true;
2738 rsurface_modelvertex3f = rsurface_model->surfmesh.data_vertex3f;
2739 rsurface_modelsvector3f = rsurface_model->surfmesh.data_svector3f;
2740 rsurface_modeltvector3f = rsurface_model->surfmesh.data_tvector3f;
2741 rsurface_modelnormal3f = rsurface_model->surfmesh.data_normal3f;
2742 rsurface_generatedvertex = false;
2744 rsurface_vertex3f = rsurface_modelvertex3f;
2745 rsurface_svector3f = rsurface_modelsvector3f;
2746 rsurface_tvector3f = rsurface_modeltvector3f;
2747 rsurface_normal3f = rsurface_modelnormal3f;
2750 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
2752 // 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
2753 if (rsurface_generatedvertex)
2755 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2756 generatetangents = true;
2757 if (generatetangents)
2758 generatenormals = true;
2759 if (generatenormals && !rsurface_modelnormal3f)
2761 rsurface_normal3f = rsurface_modelnormal3f = rsurface_array_modelnormal3f;
2762 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);
2764 if (generatetangents && !rsurface_modelsvector3f)
2766 rsurface_svector3f = rsurface_modelsvector3f = rsurface_array_modelsvector3f;
2767 rsurface_tvector3f = rsurface_modeltvector3f = rsurface_array_modeltvector3f;
2768 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);
2771 // 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)
2772 if (rsurface_texture->textureflags & (Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
2774 int texturesurfaceindex;
2775 float center[3], forward[3], right[3], up[3], v[4][3];
2776 matrix4x4_t matrix1, imatrix1;
2777 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.forward, forward);
2778 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.right, right);
2779 Matrix4x4_Transform(&rsurface_entity->inversematrix, r_view.up, up);
2780 // make deformed versions of only the model vertices used by the specified surfaces
2781 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2784 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2785 // a single autosprite surface can contain multiple sprites...
2786 for (j = 0;j < surface->num_vertices - 3;j += 4)
2788 VectorClear(center);
2789 for (i = 0;i < 4;i++)
2790 VectorAdd(center, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
2791 VectorScale(center, 0.25f, center);
2792 if (rsurface_texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
2794 forward[0] = rsurface_modelorg[0] - center[0];
2795 forward[1] = rsurface_modelorg[1] - center[1];
2797 VectorNormalize(forward);
2798 right[0] = forward[1];
2799 right[1] = -forward[0];
2801 VectorSet(up, 0, 0, 1);
2803 // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
2804 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);
2805 Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
2806 for (i = 0;i < 4;i++)
2807 Matrix4x4_Transform(&imatrix1, (rsurface_modelvertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
2808 for (i = 0;i < 4;i++)
2809 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, rsurface_array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
2811 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);
2812 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);
2814 rsurface_vertex3f = rsurface_array_deformedvertex3f;
2815 rsurface_svector3f = rsurface_array_deformedsvector3f;
2816 rsurface_tvector3f = rsurface_array_deformedtvector3f;
2817 rsurface_normal3f = rsurface_array_deformednormal3f;
2821 rsurface_vertex3f = rsurface_modelvertex3f;
2822 rsurface_svector3f = rsurface_modelsvector3f;
2823 rsurface_tvector3f = rsurface_modeltvector3f;
2824 rsurface_normal3f = rsurface_modelnormal3f;
2826 R_Mesh_VertexPointer(rsurface_vertex3f);
2829 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
2831 int texturesurfaceindex;
2832 const msurface_t *surface = texturesurfacelist[0];
2833 int firstvertex = surface->num_firstvertex;
2834 int endvertex = surface->num_firstvertex + surface->num_vertices;
2835 if (texturenumsurfaces == 1)
2837 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2838 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2840 else if (r_batchmode.integer == 2)
2842 #define MAXBATCHTRIANGLES 4096
2843 int batchtriangles = 0;
2844 int batchelements[MAXBATCHTRIANGLES*3];
2845 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2847 surface = texturesurfacelist[texturesurfaceindex];
2848 if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
2850 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2853 if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
2855 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2857 firstvertex = surface->num_firstvertex;
2858 endvertex = surface->num_firstvertex + surface->num_vertices;
2862 firstvertex = min(firstvertex, surface->num_firstvertex);
2863 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2865 memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
2866 batchtriangles += surface->num_triangles;
2869 R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
2871 else if (r_batchmode.integer == 1)
2873 int firsttriangle = 0;
2874 int endtriangle = -1;
2875 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2877 surface = texturesurfacelist[texturesurfaceindex];
2878 if (surface->num_firsttriangle != endtriangle)
2880 if (endtriangle > firsttriangle)
2882 GL_LockArrays(firstvertex, endvertex - firstvertex);
2883 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2885 firstvertex = surface->num_firstvertex;
2886 endvertex = surface->num_firstvertex + surface->num_vertices;
2887 firsttriangle = surface->num_firsttriangle;
2891 firstvertex = min(firstvertex, surface->num_firstvertex);
2892 endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
2894 endtriangle = surface->num_firsttriangle + surface->num_triangles;
2896 if (endtriangle > firsttriangle)
2898 GL_LockArrays(firstvertex, endvertex - firstvertex);
2899 R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
2904 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2906 surface = texturesurfacelist[texturesurfaceindex];
2907 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2908 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2913 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
2915 int texturesurfaceindex;
2916 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2918 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2919 int k = (int)(((size_t)surface) / sizeof(msurface_t));
2920 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);
2921 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2922 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
2926 static void RSurf_DrawBatch_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
2928 int texturesurfaceindex;
2936 vec3_t ambientcolor;
2937 vec3_t diffusecolor;
2939 VectorCopy(rsurface_entity->modellight_lightdir, lightdir);
2940 ambientcolor[0] = rsurface_entity->modellight_ambient[0] * r * 0.5f;
2941 ambientcolor[1] = rsurface_entity->modellight_ambient[1] * g * 0.5f;
2942 ambientcolor[2] = rsurface_entity->modellight_ambient[2] * b * 0.5f;
2943 diffusecolor[0] = rsurface_entity->modellight_diffuse[0] * r * 0.5f;
2944 diffusecolor[1] = rsurface_entity->modellight_diffuse[1] * g * 0.5f;
2945 diffusecolor[2] = rsurface_entity->modellight_diffuse[2] * b * 0.5f;
2946 if (VectorLength2(diffusecolor) > 0)
2948 // generate color arrays for the surfaces in this list
2949 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2951 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2952 int numverts = surface->num_vertices;
2953 v = rsurface_vertex3f + 3 * surface->num_firstvertex;
2954 c2 = rsurface_normal3f + 3 * surface->num_firstvertex;
2955 c = rsurface_array_color4f + 4 * surface->num_firstvertex;
2956 // q3-style directional shading
2957 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
2959 if ((f = DotProduct(c2, lightdir)) > 0)
2960 VectorMA(ambientcolor, f, diffusecolor, c);
2962 VectorCopy(ambientcolor, c);
2971 rsurface_lightmapcolor4f = rsurface_array_color4f;
2975 r = ambientcolor[0];
2976 g = ambientcolor[1];
2977 b = ambientcolor[2];
2978 rsurface_lightmapcolor4f = NULL;
2981 else if (lightmode >= 1 || !rsurface_lightmaptexture)
2983 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
2985 // generate color arrays for the surfaces in this list
2986 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2988 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
2989 for (i = 0, c = rsurface_array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
2991 if (surface->lightmapinfo->samples)
2993 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface_model->surfmesh.data_lightmapoffsets + surface->num_firstvertex)[i];
2994 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
2995 VectorScale(lm, scale, c);
2996 if (surface->lightmapinfo->styles[1] != 255)
2998 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
3000 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
3001 VectorMA(c, scale, lm, c);
3002 if (surface->lightmapinfo->styles[2] != 255)
3005 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
3006 VectorMA(c, scale, lm, c);
3007 if (surface->lightmapinfo->styles[3] != 255)
3010 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
3011 VectorMA(c, scale, lm, c);
3021 rsurface_lightmapcolor4f = rsurface_array_color4f;
3024 rsurface_lightmapcolor4f = rsurface_model->surfmesh.data_lightmapcolor4f;
3029 rsurface_lightmapcolor4f = NULL;
3033 if (rsurface_lightmapcolor4f)
3035 // generate color arrays for the surfaces in this list
3036 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3038 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3039 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)
3041 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3051 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3053 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3054 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)
3056 f = 1 - VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3064 rsurface_lightmapcolor4f = rsurface_array_color4f;
3066 if (applycolor && rsurface_lightmapcolor4f)
3068 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3070 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3071 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)
3079 rsurface_lightmapcolor4f = rsurface_array_color4f;
3081 R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
3082 GL_Color(r, g, b, a);
3083 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3086 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
3088 if (rsurface_mode != RSURFMODE_SHOWSURFACES)
3090 rsurface_mode = RSURFMODE_SHOWSURFACES;
3092 GL_BlendFunc(GL_ONE, GL_ZERO);
3093 R_Mesh_ColorPointer(NULL);
3094 R_Mesh_ResetTextureState();
3096 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3097 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3100 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
3102 // transparent sky would be ridiculous
3103 if ((rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
3105 if (rsurface_mode != RSURFMODE_SKY)
3107 if (rsurface_mode == RSURFMODE_GLSL)
3109 qglUseProgramObjectARB(0);CHECKGLERROR
3111 rsurface_mode = RSURFMODE_SKY;
3115 skyrendernow = false;
3117 // restore entity matrix
3118 R_Mesh_Matrix(&rsurface_entity->matrix);
3121 // LordHavoc: HalfLife maps have freaky skypolys so don't use
3122 // skymasking on them, and Quake3 never did sky masking (unlike
3123 // software Quake and software Quake2), so disable the sky masking
3124 // in Quake3 maps as it causes problems with q3map2 sky tricks,
3125 // and skymasking also looks very bad when noclipping outside the
3126 // level, so don't use it then either.
3127 if (rsurface_model->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
3129 GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1);
3130 R_Mesh_ColorPointer(NULL);
3131 R_Mesh_ResetTextureState();
3132 if (skyrendermasked)
3134 // depth-only (masking)
3135 GL_ColorMask(0,0,0,0);
3136 // just to make sure that braindead drivers don't draw
3137 // anything despite that colormask...
3138 GL_BlendFunc(GL_ZERO, GL_ONE);
3143 GL_BlendFunc(GL_ONE, GL_ZERO);
3145 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
3146 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3147 if (skyrendermasked)
3148 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
3152 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
3155 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3156 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3157 if (rsurface_mode != RSURFMODE_GLSL)
3159 rsurface_mode = RSURFMODE_GLSL;
3160 rsurface_glsl_texture = NULL;
3161 rsurface_glsl_uselightmap = false;
3162 R_Mesh_ResetTextureState();
3164 if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
3166 rsurface_glsl_texture = rsurface_texture;
3167 rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
3168 GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
3169 GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
3170 GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
3171 R_SetupSurfaceShader(vec3_origin, lightmode == 2);
3172 //permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
3173 //if (r_glsl_deluxemapping.integer)
3174 // permutation_deluxemapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, true);
3175 R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
3176 R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
3177 GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
3179 if (!r_glsl_permutation)
3181 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
3182 R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
3183 R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
3184 R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
3185 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
3187 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3188 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3189 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3190 R_Mesh_ColorPointer(NULL);
3192 else if (rsurface_lightmaptexture)
3194 R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
3195 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3196 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
3197 R_Mesh_ColorPointer(NULL);
3201 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
3202 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
3203 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
3204 R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
3206 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3209 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
3211 // OpenGL 1.3 path - anything not completely ancient
3212 int texturesurfaceindex;
3214 qboolean applycolor;
3218 const texturelayer_t *layer;
3220 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3221 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3222 if (rsurface_mode != RSURFMODE_MULTIPASS)
3223 rsurface_mode = RSURFMODE_MULTIPASS;
3224 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3225 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3228 int layertexrgbscale;
3229 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3231 if (layerindex == 0)
3235 GL_AlphaTest(false);
3236 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3239 GL_DepthMask(layer->depthmask);
3240 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3241 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
3243 layertexrgbscale = 4;
3244 VectorScale(layer->color, 0.25f, layercolor);
3246 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
3248 layertexrgbscale = 2;
3249 VectorScale(layer->color, 0.5f, layercolor);
3253 layertexrgbscale = 1;
3254 VectorScale(layer->color, 1.0f, layercolor);
3256 layercolor[3] = layer->color[3];
3257 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
3258 R_Mesh_ColorPointer(NULL);
3259 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3260 switch (layer->type)
3262 case TEXTURELAYERTYPE_LITTEXTURE:
3263 memset(&m, 0, sizeof(m));
3264 if (lightmode >= 1 || !rsurface_lightmaptexture)
3265 m.tex[0] = R_GetTexture(r_texture_white);
3267 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3268 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3269 m.tex[1] = R_GetTexture(layer->texture);
3270 m.texmatrix[1] = layer->texmatrix;
3271 m.texrgbscale[1] = layertexrgbscale;
3272 m.pointer_texcoord[1] = rsurface_model->surfmesh.data_texcoordtexture2f;
3273 R_Mesh_TextureState(&m);
3274 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], lightmode, applycolor, applyfog);
3276 case TEXTURELAYERTYPE_TEXTURE:
3277 memset(&m, 0, sizeof(m));
3278 m.tex[0] = R_GetTexture(layer->texture);
3279 m.texmatrix[0] = layer->texmatrix;
3280 m.texrgbscale[0] = layertexrgbscale;
3281 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3282 R_Mesh_TextureState(&m);
3283 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], 0, applycolor, applyfog);
3285 case TEXTURELAYERTYPE_FOG:
3286 memset(&m, 0, sizeof(m));
3287 m.texrgbscale[0] = layertexrgbscale;
3290 m.tex[0] = R_GetTexture(layer->texture);
3291 m.texmatrix[0] = layer->texmatrix;
3292 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3294 R_Mesh_TextureState(&m);
3295 // generate a color array for the fog pass
3296 R_Mesh_ColorPointer(rsurface_array_color4f);
3297 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3301 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3302 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)
3304 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3305 c[0] = layercolor[0];
3306 c[1] = layercolor[1];
3307 c[2] = layercolor[2];
3308 c[3] = f * layercolor[3];
3311 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3314 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3316 GL_LockArrays(0, 0);
3319 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3321 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3322 GL_AlphaTest(false);
3326 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
3328 // OpenGL 1.1 - crusty old voodoo path
3329 int texturesurfaceindex;
3334 const texturelayer_t *layer;
3336 // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
3337 lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
3338 if (rsurface_mode != RSURFMODE_MULTIPASS)
3339 rsurface_mode = RSURFMODE_MULTIPASS;
3340 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
3341 for (layerindex = 0, layer = rsurface_texture->currentlayers;layerindex < rsurface_texture->currentnumlayers;layerindex++, layer++)
3343 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3345 if (layerindex == 0)
3349 GL_AlphaTest(false);
3350 qglDepthFunc(GL_EQUAL);CHECKGLERROR
3353 GL_DepthMask(layer->depthmask);
3354 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
3355 R_Mesh_ColorPointer(NULL);
3356 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
3357 switch (layer->type)
3359 case TEXTURELAYERTYPE_LITTEXTURE:
3360 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
3362 // two-pass lit texture with 2x rgbscale
3363 // first the lightmap pass
3364 memset(&m, 0, sizeof(m));
3365 if (lightmode >= 1 || !rsurface_lightmaptexture)
3366 m.tex[0] = R_GetTexture(r_texture_white);
3368 m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
3369 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
3370 R_Mesh_TextureState(&m);
3371 RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
3372 GL_LockArrays(0, 0);
3373 // then apply the texture to it
3374 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3375 memset(&m, 0, sizeof(m));
3376 m.tex[0] = R_GetTexture(layer->texture);
3377 m.texmatrix[0] = layer->texmatrix;
3378 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3379 R_Mesh_TextureState(&m);
3380 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);
3384 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
3385 memset(&m, 0, sizeof(m));
3386 m.tex[0] = R_GetTexture(layer->texture);
3387 m.texmatrix[0] = layer->texmatrix;
3388 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3389 R_Mesh_TextureState(&m);
3390 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);
3393 case TEXTURELAYERTYPE_TEXTURE:
3394 // singletexture unlit texture with transparency support
3395 memset(&m, 0, sizeof(m));
3396 m.tex[0] = R_GetTexture(layer->texture);
3397 m.texmatrix[0] = layer->texmatrix;
3398 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3399 R_Mesh_TextureState(&m);
3400 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);
3402 case TEXTURELAYERTYPE_FOG:
3403 // singletexture fogging
3404 R_Mesh_ColorPointer(rsurface_array_color4f);
3407 memset(&m, 0, sizeof(m));
3408 m.tex[0] = R_GetTexture(layer->texture);
3409 m.texmatrix[0] = layer->texmatrix;
3410 m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordtexture2f;
3411 R_Mesh_TextureState(&m);
3414 R_Mesh_ResetTextureState();
3415 // generate a color array for the fog pass
3416 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3420 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3421 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)
3423 f = VERTEXFOGTABLE(VectorDistance(v, rsurface_modelorg));
3424 c[0] = layer->color[0];
3425 c[1] = layer->color[1];
3426 c[2] = layer->color[2];
3427 c[3] = f * layer->color[3];
3430 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
3433 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
3435 GL_LockArrays(0, 0);
3438 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
3440 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3441 GL_AlphaTest(false);
3445 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3447 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_NODRAW)
3449 r_shadow_rtlight = NULL;
3450 r_refdef.stats.entities_surfaces += texturenumsurfaces;
3452 GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
3453 GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
3454 if (r_showsurfaces.integer)
3455 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
3456 else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
3457 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
3458 else if (rsurface_texture->currentnumlayers)
3460 if (r_glsl.integer && gl_support_fragment_shader)
3461 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
3462 else if (gl_combine.integer && r_textureunits.integer >= 2)
3463 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
3465 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
3468 GL_LockArrays(0, 0);
3471 #define BATCHSIZE 256
3472 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3474 int surfacelistindex;
3477 msurface_t *texturesurfacelist[BATCHSIZE];
3478 // if the model is static it doesn't matter what value we give for
3479 // wantnormals and wanttangents, so this logic uses only rules applicable
3480 // to a model, knowing that they are meaningless otherwise
3481 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3482 RSurf_ActiveEntity(ent, false, false);
3484 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3487 for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
3489 msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
3491 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3494 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
3495 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3497 t = surface->texture;
3498 rsurface_lightmaptexture = surface->lightmaptexture;
3499 R_UpdateTextureInfo(ent, t);
3500 rsurface_texture = t->currentframe;
3503 texturesurfacelist[batchcount++] = surface;
3506 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
3507 R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
3511 void R_QueueTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist)
3513 int texturesurfaceindex;
3514 vec3_t tempcenter, center;
3515 if (rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED)
3517 // drawing sky transparently would be too difficult
3518 if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY))
3520 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
3522 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
3523 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
3524 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
3525 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
3526 Matrix4x4_Transform(&rsurface_entity->matrix, tempcenter, center);
3527 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);
3532 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
3535 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
3536 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
3538 int i, j, f, flagsmask;
3539 int counttriangles = 0;
3541 model_t *model = ent->model;
3542 const int maxsurfacelist = 1024;
3543 int numsurfacelist = 0;
3544 msurface_t *surfacelist[1024];
3548 // if the model is static it doesn't matter what value we give for
3549 // wantnormals and wanttangents, so this logic uses only rules applicable
3550 // to a model, knowing that they are meaningless otherwise
3551 if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
3552 RSurf_ActiveEntity(ent, false, false);
3554 RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
3556 // update light styles
3557 if (!skysurfaces && model->brushq1.light_styleupdatechains)
3559 msurface_t *surface, **surfacechain;
3560 for (i = 0;i < model->brushq1.light_styles;i++)
3562 if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
3564 model->brushq1.light_stylevalue[i] = r_refdef.lightstylevalue[model->brushq1.light_style[i]];
3565 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
3566 for (;(surface = *surfacechain);surfacechain++)
3567 surface->cached_dlight = true;
3572 R_UpdateAllTextureInfo(ent);
3573 flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
3576 rsurface_lightmaptexture = NULL;
3577 rsurface_texture = NULL;
3579 if (ent == r_refdef.worldentity)
3581 msurface_t *surface;
3582 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3584 if (!r_viewcache.world_surfacevisible[j])
3586 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3590 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3593 t = surface->texture;
3594 rsurface_lightmaptexture = surface->lightmaptexture;
3595 rsurface_texture = t->currentframe;
3596 f = rsurface_texture->currentmaterialflags & flagsmask;
3598 if (f && surface->num_triangles)
3600 // if lightmap parameters changed, rebuild lightmap texture
3601 if (surface->cached_dlight)
3602 R_BuildLightMap(ent, surface);
3603 // add face to draw list
3604 surfacelist[numsurfacelist++] = surface;
3605 counttriangles += surface->num_triangles;
3606 if (numsurfacelist >= maxsurfacelist)
3608 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3616 msurface_t *surface;
3617 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3619 if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
3623 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3626 t = surface->texture;
3627 rsurface_lightmaptexture = surface->lightmaptexture;
3628 rsurface_texture = t->currentframe;
3629 f = rsurface_texture->currentmaterialflags & flagsmask;
3631 if (f && surface->num_triangles)
3633 // if lightmap parameters changed, rebuild lightmap texture
3634 if (surface->cached_dlight)
3635 R_BuildLightMap(ent, surface);
3636 // add face to draw list
3637 surfacelist[numsurfacelist++] = surface;
3638 counttriangles += surface->num_triangles;
3639 if (numsurfacelist >= maxsurfacelist)
3641 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3648 R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
3649 r_refdef.stats.entities_triangles += counttriangles;
3652 if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
3655 const msurface_t *surface;
3658 R_Mesh_Matrix(&ent->matrix);
3659 R_Mesh_ColorPointer(NULL);
3660 R_Mesh_ResetTextureState();
3661 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3662 GL_DepthMask(false);
3663 GL_DepthTest(!r_showdisabledepthtest.integer);
3664 qglPolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);CHECKGLERROR
3665 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
3666 if (brush->colbrushf && brush->colbrushf->numtriangles)
3667 R_DrawCollisionBrush(brush->colbrushf);
3668 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
3669 if (surface->num_collisiontriangles)
3670 R_DrawCollisionSurface(ent, surface);
3671 qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
3674 if (r_showtris.integer || r_shownormals.integer)
3677 msurface_t *surface;
3678 const int *elements;
3683 if (r_showdisabledepthtest.integer)
3685 qglDepthFunc(GL_ALWAYS);CHECKGLERROR
3687 GL_BlendFunc(GL_ONE, GL_ZERO);
3688 R_Mesh_ColorPointer(NULL);
3689 R_Mesh_ResetTextureState();
3690 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
3692 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
3694 rsurface_texture = surface->texture->currentframe;
3695 if ((rsurface_texture->currentmaterialflags & flagsmask) && surface->num_triangles)
3697 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
3698 if (r_showtris.integer)
3700 if (!rsurface_texture->currentlayers->depthmask)
3701 GL_Color(r_showtris.value * r_view.colorscale, 0, 0, 1);
3702 else if (ent == r_refdef.worldentity)
3703 GL_Color(r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, r_showtris.value * r_view.colorscale, 1);
3705 GL_Color(0, r_showtris.value * r_view.colorscale, 0, 1);
3706 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
3709 for (k = 0;k < surface->num_triangles;k++, elements += 3)
3711 qglArrayElement(elements[0]);qglArrayElement(elements[1]);
3712 qglArrayElement(elements[1]);qglArrayElement(elements[2]);
3713 qglArrayElement(elements[2]);qglArrayElement(elements[0]);
3718 if (r_shownormals.integer)
3720 GL_Color(r_shownormals.value * r_view.colorscale, 0, 0, 1);
3722 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3724 VectorCopy(rsurface_vertex3f + l * 3, v);
3725 qglVertex3f(v[0], v[1], v[2]);
3726 VectorMA(v, 8, rsurface_svector3f + l * 3, v);
3727 qglVertex3f(v[0], v[1], v[2]);
3731 GL_Color(0, 0, r_shownormals.value * r_view.colorscale, 1);
3733 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3735 VectorCopy(rsurface_vertex3f + l * 3, v);
3736 qglVertex3f(v[0], v[1], v[2]);
3737 VectorMA(v, 8, rsurface_tvector3f + l * 3, v);
3738 qglVertex3f(v[0], v[1], v[2]);
3742 GL_Color(0, r_shownormals.value * r_view.colorscale, 0, 1);
3744 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
3746 VectorCopy(rsurface_vertex3f + l * 3, v);
3747 qglVertex3f(v[0], v[1], v[2]);
3748 VectorMA(v, 8, rsurface_normal3f + l * 3, v);
3749 qglVertex3f(v[0], v[1], v[2]);
3756 rsurface_texture = NULL;
3757 if (r_showdisabledepthtest.integer)
3759 qglDepthFunc(GL_LEQUAL);CHECKGLERROR