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.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
36 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
37 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
38 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
39 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
40 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
41 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
42 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"};
43 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"};
44 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
45 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"};
46 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"};
47 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"};
48 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
49 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
50 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
51 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
52 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
53 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
54 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
55 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
56 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
57 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
58 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
59 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
60 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
61 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
62 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
63 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
64 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
65 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
74 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
76 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)"};
78 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
79 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
80 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
81 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
82 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
83 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
85 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
86 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
87 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
88 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
89 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
91 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
92 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
93 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
94 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
96 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
97 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
98 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
99 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
100 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
101 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
102 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
104 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
105 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
106 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
107 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
109 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"};
111 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"};
113 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
115 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
116 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
117 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
118 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
119 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
120 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
122 extern qboolean v_flipped_state;
124 typedef struct r_glsl_bloomshader_s
127 int loc_Texture_Bloom;
129 r_glsl_bloomshader_t;
131 static struct r_bloomstate_s
136 int bloomwidth, bloomheight;
138 int screentexturewidth, screentextureheight;
139 rtexture_t *texture_screen;
141 int bloomtexturewidth, bloomtextureheight;
142 rtexture_t *texture_bloom;
144 r_glsl_bloomshader_t *shader;
146 // arrays for rendering the screen passes
147 float screentexcoord2f[8];
148 float bloomtexcoord2f[8];
149 float offsettexcoord2f[8];
153 typedef struct r_waterstate_waterplane_s
155 rtexture_t *texture_refraction;
156 rtexture_t *texture_reflection;
158 int materialflags; // combined flags of all water surfaces on this plane
159 unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
162 r_waterstate_waterplane_t;
164 #define MAX_WATERPLANES 16
166 static struct r_waterstate_s
170 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
172 int waterwidth, waterheight;
173 int texturewidth, textureheight;
175 int maxwaterplanes; // same as MAX_WATERPLANES
177 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
179 float screenscale[2];
180 float screencenter[2];
184 // shadow volume bsp struct with automatically growing nodes buffer
187 rtexture_t *r_texture_blanknormalmap;
188 rtexture_t *r_texture_white;
189 rtexture_t *r_texture_grey128;
190 rtexture_t *r_texture_black;
191 rtexture_t *r_texture_notexture;
192 rtexture_t *r_texture_whitecube;
193 rtexture_t *r_texture_normalizationcube;
194 rtexture_t *r_texture_fogattenuation;
195 //rtexture_t *r_texture_fogintensity;
197 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
198 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
200 // vertex coordinates for a quad that covers the screen exactly
201 const static float r_screenvertex3f[12] =
209 extern void R_DrawModelShadows(void);
211 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
214 for (i = 0;i < verts;i++)
225 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
228 for (i = 0;i < verts;i++)
238 // FIXME: move this to client?
241 if (gamemode == GAME_NEHAHRA)
243 Cvar_Set("gl_fogenable", "0");
244 Cvar_Set("gl_fogdensity", "0.2");
245 Cvar_Set("gl_fogred", "0.3");
246 Cvar_Set("gl_foggreen", "0.3");
247 Cvar_Set("gl_fogblue", "0.3");
249 r_refdef.fog_density = 0;
250 r_refdef.fog_red = 0;
251 r_refdef.fog_green = 0;
252 r_refdef.fog_blue = 0;
253 r_refdef.fog_alpha = 1;
254 r_refdef.fog_start = 0;
255 r_refdef.fog_end = 0;
258 float FogForDistance(vec_t dist)
260 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
261 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
264 float FogPoint_World(const vec3_t p)
266 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
269 float FogPoint_Model(const vec3_t p)
271 return FogForDistance(VectorDistance((p), rsurface.modelorg));
274 static void R_BuildBlankTextures(void)
276 unsigned char data[4];
277 data[2] = 128; // normal X
278 data[1] = 128; // normal Y
279 data[0] = 255; // normal Z
280 data[3] = 128; // height
281 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
286 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
291 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
296 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
299 static void R_BuildNoTexture(void)
302 unsigned char pix[16][16][4];
303 // this makes a light grey/dark grey checkerboard texture
304 for (y = 0;y < 16;y++)
306 for (x = 0;x < 16;x++)
308 if ((y < 8) ^ (x < 8))
324 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
327 static void R_BuildWhiteCube(void)
329 unsigned char data[6*1*1*4];
330 memset(data, 255, sizeof(data));
331 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
334 static void R_BuildNormalizationCube(void)
338 vec_t s, t, intensity;
340 unsigned char data[6][NORMSIZE][NORMSIZE][4];
341 for (side = 0;side < 6;side++)
343 for (y = 0;y < NORMSIZE;y++)
345 for (x = 0;x < NORMSIZE;x++)
347 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
348 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
383 intensity = 127.0f / sqrt(DotProduct(v, v));
384 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
385 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
386 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
387 data[side][y][x][3] = 255;
391 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
394 static void R_BuildFogTexture(void)
398 unsigned char data1[FOGWIDTH][4];
399 //unsigned char data2[FOGWIDTH][4];
402 r_refdef.fogmasktable_start = r_refdef.fog_start;
403 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
404 r_refdef.fogmasktable_range = r_refdef.fogrange;
405 r_refdef.fogmasktable_density = r_refdef.fog_density;
407 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
408 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
410 d = (x * r - r_refdef.fogmasktable_start);
411 if(developer.integer >= 100)
412 Con_Printf("%f ", d);
414 if (r_fog_exp2.integer)
415 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
417 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
418 if(developer.integer >= 100)
419 Con_Printf(" : %f ", alpha);
420 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
421 if(developer.integer >= 100)
422 Con_Printf(" = %f\n", alpha);
423 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
426 for (x = 0;x < FOGWIDTH;x++)
428 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
433 //data2[x][0] = 255 - b;
434 //data2[x][1] = 255 - b;
435 //data2[x][2] = 255 - b;
438 if (r_texture_fogattenuation)
440 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
441 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
445 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
446 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
450 static const char *builtinshaderstring =
451 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
452 "// written by Forest 'LordHavoc' Hale\n"
454 "// common definitions between vertex shader and fragment shader:\n"
456 "#ifdef __GLSL_CG_DATA_TYPES\n"
457 "# define myhalf half\n"
458 "# define myhalf2 half2\n"
459 "# define myhalf3 half3\n"
460 "# define myhalf4 half4\n"
462 "# define myhalf float\n"
463 "# define myhalf2 vec2\n"
464 "# define myhalf3 vec3\n"
465 "# define myhalf4 vec4\n"
468 "varying vec2 TexCoord;\n"
469 "varying vec2 TexCoordLightmap;\n"
471 "//#ifdef MODE_LIGHTSOURCE\n"
472 "varying vec3 CubeVector;\n"
475 "//#ifdef MODE_LIGHTSOURCE\n"
476 "varying vec3 LightVector;\n"
478 "//# ifdef MODE_LIGHTDIRECTION\n"
479 "//varying vec3 LightVector;\n"
483 "varying vec3 EyeVector;\n"
485 "varying vec3 EyeVectorModelSpace;\n"
488 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
489 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
490 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
492 "//#ifdef MODE_WATER\n"
493 "varying vec4 ModelViewProjectionPosition;\n"
495 "//# ifdef MODE_REFRACTION\n"
496 "//varying vec4 ModelViewProjectionPosition;\n"
498 "//# ifdef USEREFLECTION\n"
499 "//varying vec4 ModelViewProjectionPosition;\n"
508 "// vertex shader specific:\n"
509 "#ifdef VERTEX_SHADER\n"
511 "uniform vec3 LightPosition;\n"
512 "uniform vec3 EyePosition;\n"
513 "uniform vec3 LightDir;\n"
515 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
519 " gl_FrontColor = gl_Color;\n"
520 " // copy the surface texcoord\n"
521 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
522 "#ifndef MODE_LIGHTSOURCE\n"
523 "# ifndef MODE_LIGHTDIRECTION\n"
524 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
528 "#ifdef MODE_LIGHTSOURCE\n"
529 " // transform vertex position into light attenuation/cubemap space\n"
530 " // (-1 to +1 across the light box)\n"
531 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
533 " // transform unnormalized light direction into tangent space\n"
534 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
535 " // normalize it per pixel)\n"
536 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
537 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
538 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
539 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
542 "#ifdef MODE_LIGHTDIRECTION\n"
543 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
544 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
545 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
548 " // transform unnormalized eye direction into tangent space\n"
550 " vec3 EyeVectorModelSpace;\n"
552 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
553 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
554 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
555 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
557 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
558 " VectorS = gl_MultiTexCoord1.xyz;\n"
559 " VectorT = gl_MultiTexCoord2.xyz;\n"
560 " VectorR = gl_MultiTexCoord3.xyz;\n"
563 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
564 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
565 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
566 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
569 "// transform vertex to camera space, using ftransform to match non-VS\n"
571 " gl_Position = ftransform();\n"
573 "#ifdef MODE_WATER\n"
574 " ModelViewProjectionPosition = gl_Position;\n"
576 "#ifdef MODE_REFRACTION\n"
577 " ModelViewProjectionPosition = gl_Position;\n"
579 "#ifdef USEREFLECTION\n"
580 " ModelViewProjectionPosition = gl_Position;\n"
584 "#endif // VERTEX_SHADER\n"
589 "// fragment shader specific:\n"
590 "#ifdef FRAGMENT_SHADER\n"
592 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
593 "uniform sampler2D Texture_Normal;\n"
594 "uniform sampler2D Texture_Color;\n"
595 "uniform sampler2D Texture_Gloss;\n"
596 "uniform samplerCube Texture_Cube;\n"
597 "uniform sampler2D Texture_Attenuation;\n"
598 "uniform sampler2D Texture_FogMask;\n"
599 "uniform sampler2D Texture_Pants;\n"
600 "uniform sampler2D Texture_Shirt;\n"
601 "uniform sampler2D Texture_Lightmap;\n"
602 "uniform sampler2D Texture_Deluxemap;\n"
603 "uniform sampler2D Texture_Glow;\n"
604 "uniform sampler2D Texture_Reflection;\n"
605 "uniform sampler2D Texture_Refraction;\n"
607 "uniform myhalf3 LightColor;\n"
608 "uniform myhalf3 AmbientColor;\n"
609 "uniform myhalf3 DiffuseColor;\n"
610 "uniform myhalf3 SpecularColor;\n"
611 "uniform myhalf3 Color_Pants;\n"
612 "uniform myhalf3 Color_Shirt;\n"
613 "uniform myhalf3 FogColor;\n"
615 "uniform myhalf4 TintColor;\n"
618 "//#ifdef MODE_WATER\n"
619 "uniform vec4 DistortScaleRefractReflect;\n"
620 "uniform vec4 ScreenScaleRefractReflect;\n"
621 "uniform vec4 ScreenCenterRefractReflect;\n"
622 "uniform myhalf4 RefractColor;\n"
623 "uniform myhalf4 ReflectColor;\n"
624 "uniform myhalf ReflectFactor;\n"
625 "uniform myhalf ReflectOffset;\n"
627 "//# ifdef MODE_REFRACTION\n"
628 "//uniform vec4 DistortScaleRefractReflect;\n"
629 "//uniform vec4 ScreenScaleRefractReflect;\n"
630 "//uniform vec4 ScreenCenterRefractReflect;\n"
631 "//uniform myhalf4 RefractColor;\n"
632 "//# ifdef USEREFLECTION\n"
633 "//uniform myhalf4 ReflectColor;\n"
636 "//# ifdef USEREFLECTION\n"
637 "//uniform vec4 DistortScaleRefractReflect;\n"
638 "//uniform vec4 ScreenScaleRefractReflect;\n"
639 "//uniform vec4 ScreenCenterRefractReflect;\n"
640 "//uniform myhalf4 ReflectColor;\n"
645 "uniform myhalf GlowScale;\n"
646 "uniform myhalf SceneBrightness;\n"
647 "#ifdef USECONTRASTBOOST\n"
648 "uniform myhalf ContrastBoostCoeff;\n"
651 "uniform float OffsetMapping_Scale;\n"
652 "uniform float OffsetMapping_Bias;\n"
653 "uniform float FogRangeRecip;\n"
655 "uniform myhalf AmbientScale;\n"
656 "uniform myhalf DiffuseScale;\n"
657 "uniform myhalf SpecularScale;\n"
658 "uniform myhalf SpecularPower;\n"
660 "#ifdef USEOFFSETMAPPING\n"
661 "vec2 OffsetMapping(vec2 TexCoord)\n"
663 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
664 " // 14 sample relief mapping: linear search and then binary search\n"
665 " // this basically steps forward a small amount repeatedly until it finds\n"
666 " // itself inside solid, then jitters forward and back using decreasing\n"
667 " // amounts to find the impact\n"
668 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
669 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
670 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
671 " vec3 RT = vec3(TexCoord, 1);\n"
672 " OffsetVector *= 0.1;\n"
673 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
674 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
675 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
676 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
677 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
678 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
679 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
680 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
681 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
682 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
683 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
684 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
685 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
686 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
689 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
690 " // this basically moves forward the full distance, and then backs up based\n"
691 " // on height of samples\n"
692 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
693 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
694 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
695 " TexCoord += OffsetVector;\n"
696 " OffsetVector *= 0.333;\n"
697 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
698 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
699 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
700 " return TexCoord;\n"
703 "#endif // USEOFFSETMAPPING\n"
705 "#ifdef MODE_WATER\n"
710 "#ifdef USEOFFSETMAPPING\n"
711 " // apply offsetmapping\n"
712 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
713 "#define TexCoord TexCoordOffset\n"
716 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
717 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
718 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
719 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 5.0) * ReflectFactor + ReflectOffset;\n"
720 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
723 "#else // MODE_WATER\n"
724 "#ifdef MODE_REFRACTION\n"
726 "// refraction pass\n"
729 "#ifdef USEOFFSETMAPPING\n"
730 " // apply offsetmapping\n"
731 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
732 "#define TexCoord TexCoordOffset\n"
735 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
736 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
737 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
738 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
741 "#else // MODE_REFRACTION\n"
744 "#ifdef USEOFFSETMAPPING\n"
745 " // apply offsetmapping\n"
746 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
747 "#define TexCoord TexCoordOffset\n"
750 " // combine the diffuse textures (base, pants, shirt)\n"
751 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
752 "#ifdef USECOLORMAPPING\n"
753 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
759 "#ifdef MODE_LIGHTSOURCE\n"
762 " // calculate surface normal, light normal, and specular normal\n"
763 " // compute color intensity for the two textures (colormap and glossmap)\n"
764 " // scale by light color and attenuation as efficiently as possible\n"
765 " // (do as much scalar math as possible rather than vector math)\n"
766 "# ifdef USESPECULAR\n"
767 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
768 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
769 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
771 " // calculate directional shading\n"
772 " color.rgb = LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * myhalf3(texture2D(Texture_Gloss, TexCoord)));\n"
774 "# ifdef USEDIFFUSE\n"
775 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
776 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
778 " // calculate directional shading\n"
779 " color.rgb = color.rgb * LightColor * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
781 " // calculate directionless shading\n"
782 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
786 "# ifdef USECUBEFILTER\n"
787 " // apply light cubemap filter\n"
788 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
789 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
791 "#endif // MODE_LIGHTSOURCE\n"
796 "#ifdef MODE_LIGHTDIRECTION\n"
797 " // directional model lighting\n"
798 "# ifdef USESPECULAR\n"
799 " // get the surface normal and light normal\n"
800 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
801 " myhalf3 diffusenormal = myhalf3(LightVector);\n"
803 " // calculate directional shading\n"
804 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
805 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
806 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
808 "# ifdef USEDIFFUSE\n"
809 " // get the surface normal and light normal\n"
810 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
811 " myhalf3 diffusenormal = myhalf3(LightVector);\n"
813 " // calculate directional shading\n"
814 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
816 " color.rgb *= AmbientColor;\n"
820 " color.a *= TintColor.a;\n"
821 "#endif // MODE_LIGHTDIRECTION\n"
826 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
827 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
829 " // get the surface normal and light normal\n"
830 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
832 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5);\n"
833 " myhalf3 diffusenormal = normalize(myhalf3(dot(diffusenormal_modelspace, myhalf3(VectorS)), dot(diffusenormal_modelspace, myhalf3(VectorT)), dot(diffusenormal_modelspace, myhalf3(VectorR))));\n"
834 " // calculate directional shading\n"
835 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
836 "# ifdef USESPECULAR\n"
837 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
838 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
841 " // apply lightmap color\n"
842 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
844 " color *= TintColor;\n"
845 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
850 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
851 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
853 " // get the surface normal and light normal\n"
854 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
856 " myhalf3 diffusenormal = normalize(myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5));\n"
857 " // calculate directional shading\n"
858 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
859 "# ifdef USESPECULAR\n"
860 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
861 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
864 " // apply lightmap color\n"
865 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
867 " color *= TintColor;\n"
868 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
873 "#ifdef MODE_LIGHTMAP\n"
874 " // apply lightmap color\n"
875 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
877 " color *= TintColor;\n"
878 "#endif // MODE_LIGHTMAP\n"
883 "#ifdef MODE_VERTEXCOLOR\n"
884 " // apply lightmap color\n"
885 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
887 " color *= TintColor;\n"
888 "#endif // MODE_VERTEXCOLOR\n"
893 "#ifdef MODE_FLATCOLOR\n"
894 " color *= TintColor;\n"
895 "#endif // MODE_FLATCOLOR\n"
905 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
908 "#ifdef USECONTRASTBOOST\n"
909 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
912 " color.rgb *= SceneBrightness;\n"
914 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
916 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
919 " // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
920 "#ifdef USEREFLECTION\n"
921 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
922 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
923 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
924 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
927 " gl_FragColor = vec4(color);\n"
929 "#endif // MODE_REFRACTION\n"
930 "#endif // MODE_WATER\n"
932 "#endif // FRAGMENT_SHADER\n"
935 typedef struct shaderpermutationinfo_s
940 shaderpermutationinfo_t;
942 typedef struct shadermodeinfo_s
944 const char *vertexfilename;
945 const char *geometryfilename;
946 const char *fragmentfilename;
952 typedef enum shaderpermutation_e
954 SHADERPERMUTATION_COLORMAPPING = 1<<0, // indicates this is a colormapped skin
955 SHADERPERMUTATION_CONTRASTBOOST = 1<<1, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
956 SHADERPERMUTATION_FOG = 1<<2, // tint the color by fog color or black if using additive blend mode
957 SHADERPERMUTATION_CUBEFILTER = 1<<3, // (lightsource) use cubemap light filter
958 SHADERPERMUTATION_GLOW = 1<<4, // (lightmap) blend in an additive glow texture
959 SHADERPERMUTATION_DIFFUSE = 1<<5, // (lightsource) whether to use directional shading
960 SHADERPERMUTATION_SPECULAR = 1<<6, // (lightsource or deluxemapping) render specular effects
961 SHADERPERMUTATION_REFLECTION = 1<<7, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
962 SHADERPERMUTATION_OFFSETMAPPING = 1<<8, // adjust texcoords to roughly simulate a displacement mapped surface
963 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<9, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
964 SHADERPERMUTATION_LIMIT = 1<<10, // size of permutations array
965 SHADERPERMUTATION_COUNT = 10 // size of shaderpermutationinfo array
969 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
970 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
972 {"#define USECOLORMAPPING\n", " colormapping"},
973 {"#define USECONTRASTBOOST\n", " contrastboost"},
974 {"#define USEFOG\n", " fog"},
975 {"#define USECUBEFILTER\n", " cubefilter"},
976 {"#define USEGLOW\n", " glow"},
977 {"#define USEDIFFUSE\n", " diffuse"},
978 {"#define USESPECULAR\n", " specular"},
979 {"#define USEREFLECTION\n", " reflection"},
980 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
981 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
984 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
985 typedef enum shadermode_e
987 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
988 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
989 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
990 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
991 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
992 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
993 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
994 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
995 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
1000 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1001 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1003 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1004 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1005 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1006 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1007 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1008 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1009 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1010 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1011 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1014 typedef struct r_glsl_permutation_s
1016 // indicates if we have tried compiling this permutation already
1018 // 0 if compilation failed
1020 // locations of detected uniforms in program object, or -1 if not found
1021 int loc_Texture_Normal;
1022 int loc_Texture_Color;
1023 int loc_Texture_Gloss;
1024 int loc_Texture_Cube;
1025 int loc_Texture_Attenuation;
1026 int loc_Texture_FogMask;
1027 int loc_Texture_Pants;
1028 int loc_Texture_Shirt;
1029 int loc_Texture_Lightmap;
1030 int loc_Texture_Deluxemap;
1031 int loc_Texture_Glow;
1032 int loc_Texture_Refraction;
1033 int loc_Texture_Reflection;
1035 int loc_LightPosition;
1036 int loc_EyePosition;
1038 int loc_Color_Pants;
1039 int loc_Color_Shirt;
1040 int loc_FogRangeRecip;
1041 int loc_AmbientScale;
1042 int loc_DiffuseScale;
1043 int loc_SpecularScale;
1044 int loc_SpecularPower;
1046 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1047 int loc_OffsetMapping_Scale;
1049 int loc_AmbientColor;
1050 int loc_DiffuseColor;
1051 int loc_SpecularColor;
1053 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1054 int loc_DistortScaleRefractReflect;
1055 int loc_ScreenScaleRefractReflect;
1056 int loc_ScreenCenterRefractReflect;
1057 int loc_RefractColor;
1058 int loc_ReflectColor;
1059 int loc_ReflectFactor;
1060 int loc_ReflectOffset;
1062 r_glsl_permutation_t;
1064 // information about each possible shader permutation
1065 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1066 // currently selected permutation
1067 r_glsl_permutation_t *r_glsl_permutation;
1069 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1072 if (!filename || !filename[0])
1074 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1077 if (printfromdisknotice)
1078 Con_DPrint("from disk... ");
1079 return shaderstring;
1081 else if (!strcmp(filename, "glsl/default.glsl"))
1083 shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1084 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1086 return shaderstring;
1089 static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t permutation)
1092 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1093 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1094 int vertstrings_count = 0;
1095 int geomstrings_count = 0;
1096 int fragstrings_count = 0;
1097 char *vertexstring, *geometrystring, *fragmentstring;
1098 const char *vertstrings_list[32+3];
1099 const char *geomstrings_list[32+3];
1100 const char *fragstrings_list[32+3];
1101 char permutationname[256];
1108 permutationname[0] = 0;
1109 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1110 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1111 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1113 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1115 // the first pretext is which type of shader to compile as
1116 // (later these will all be bound together as a program object)
1117 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1118 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1119 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1121 // the second pretext is the mode (for example a light source)
1122 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1123 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1124 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1125 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1127 // now add all the permutation pretexts
1128 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1130 if (permutation & (1<<i))
1132 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1133 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1134 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1135 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1139 // keep line numbers correct
1140 vertstrings_list[vertstrings_count++] = "\n";
1141 geomstrings_list[geomstrings_count++] = "\n";
1142 fragstrings_list[fragstrings_count++] = "\n";
1146 // now append the shader text itself
1147 vertstrings_list[vertstrings_count++] = vertexstring;
1148 geomstrings_list[geomstrings_count++] = geometrystring;
1149 fragstrings_list[fragstrings_count++] = fragmentstring;
1151 // if any sources were NULL, clear the respective list
1153 vertstrings_count = 0;
1154 if (!geometrystring)
1155 geomstrings_count = 0;
1156 if (!fragmentstring)
1157 fragstrings_count = 0;
1159 // compile the shader program
1160 if (vertstrings_count + geomstrings_count + fragstrings_count)
1161 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1165 qglUseProgramObjectARB(p->program);CHECKGLERROR
1166 // look up all the uniform variable names we care about, so we don't
1167 // have to look them up every time we set them
1168 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1169 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1170 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1171 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1172 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1173 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1174 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1175 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1176 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1177 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1178 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1179 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1180 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1181 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1182 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1183 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1184 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
1185 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1186 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1187 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1188 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1189 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1190 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1191 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1192 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1193 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1194 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1195 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1196 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1197 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1198 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1199 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1200 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1201 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1202 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1203 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1204 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1205 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1206 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1207 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1208 // initialize the samplers to refer to the texture units we use
1209 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
1210 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
1211 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
1212 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
1213 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
1214 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
1215 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
1216 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
1217 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
1218 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
1219 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
1220 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
1221 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
1223 qglUseProgramObjectARB(0);CHECKGLERROR
1224 if (developer.integer)
1225 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1228 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1232 Mem_Free(vertexstring);
1234 Mem_Free(geometrystring);
1236 Mem_Free(fragmentstring);
1239 void R_GLSL_Restart_f(void)
1242 shaderpermutation_t permutation;
1243 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1244 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1245 if (r_glsl_permutations[mode][permutation].program)
1246 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1247 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1250 void R_GLSL_DumpShader_f(void)
1254 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1257 Con_Printf("failed to write to glsl/default.glsl\n");
1261 FS_Print(file, "// The engine may define the following macros:\n");
1262 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1263 for (i = 0;i < SHADERMODE_COUNT;i++)
1264 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1265 for (i = 0;i < SHADERPERMUTATION_LIMIT;i++)
1266 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1267 FS_Print(file, "\n");
1268 FS_Print(file, builtinshaderstring);
1271 Con_Printf("glsl/default.glsl written\n");
1274 extern rtexture_t *r_shadow_attenuationgradienttexture;
1275 extern rtexture_t *r_shadow_attenuation2dtexture;
1276 extern rtexture_t *r_shadow_attenuation3dtexture;
1277 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1279 // select a permutation of the lighting shader appropriate to this
1280 // combination of texture, entity, light source, and fogging, only use the
1281 // minimum features necessary to avoid wasting rendering time in the
1282 // fragment shader on features that are not being used
1283 unsigned int permutation = 0;
1284 shadermode_t mode = 0;
1285 r_glsl_permutation = NULL;
1286 // TODO: implement geometry-shader based shadow volumes someday
1287 if (r_glsl_offsetmapping.integer)
1289 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1290 if (r_glsl_offsetmapping_reliefmapping.integer)
1291 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1293 if (rsurfacepass == RSURFPASS_BACKGROUND)
1295 // distorted background
1296 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1297 mode = SHADERMODE_WATER;
1299 mode = SHADERMODE_REFRACTION;
1301 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1304 mode = SHADERMODE_LIGHTSOURCE;
1305 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1306 permutation |= SHADERPERMUTATION_CUBEFILTER;
1307 if (diffusescale > 0)
1308 permutation |= SHADERPERMUTATION_DIFFUSE;
1309 if (specularscale > 0)
1310 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1311 if (r_refdef.fogenabled)
1312 permutation |= SHADERPERMUTATION_FOG;
1313 if (rsurface.texture->colormapping)
1314 permutation |= SHADERPERMUTATION_COLORMAPPING;
1315 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1316 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1318 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1320 // unshaded geometry (fullbright or ambient model lighting)
1321 mode = SHADERMODE_FLATCOLOR;
1322 if (rsurface.texture->currentskinframe->glow)
1323 permutation |= SHADERPERMUTATION_GLOW;
1324 if (r_refdef.fogenabled)
1325 permutation |= SHADERPERMUTATION_FOG;
1326 if (rsurface.texture->colormapping)
1327 permutation |= SHADERPERMUTATION_COLORMAPPING;
1328 if (r_glsl_offsetmapping.integer)
1330 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1331 if (r_glsl_offsetmapping_reliefmapping.integer)
1332 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1334 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1335 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1336 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1337 permutation |= SHADERPERMUTATION_REFLECTION;
1339 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1341 // directional model lighting
1342 mode = SHADERMODE_LIGHTDIRECTION;
1343 if (rsurface.texture->currentskinframe->glow)
1344 permutation |= SHADERPERMUTATION_GLOW;
1345 permutation |= SHADERPERMUTATION_DIFFUSE;
1346 if (specularscale > 0)
1347 permutation |= SHADERPERMUTATION_SPECULAR;
1348 if (r_refdef.fogenabled)
1349 permutation |= SHADERPERMUTATION_FOG;
1350 if (rsurface.texture->colormapping)
1351 permutation |= SHADERPERMUTATION_COLORMAPPING;
1352 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1353 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1354 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1355 permutation |= SHADERPERMUTATION_REFLECTION;
1357 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1359 // ambient model lighting
1360 mode = SHADERMODE_LIGHTDIRECTION;
1361 if (rsurface.texture->currentskinframe->glow)
1362 permutation |= SHADERPERMUTATION_GLOW;
1363 if (r_refdef.fogenabled)
1364 permutation |= SHADERPERMUTATION_FOG;
1365 if (rsurface.texture->colormapping)
1366 permutation |= SHADERPERMUTATION_COLORMAPPING;
1367 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1368 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1369 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1370 permutation |= SHADERPERMUTATION_REFLECTION;
1375 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1377 // deluxemapping (light direction texture)
1378 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1379 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1381 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1382 permutation |= SHADERPERMUTATION_DIFFUSE;
1383 if (specularscale > 0)
1384 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1386 else if (r_glsl_deluxemapping.integer >= 2)
1388 // fake deluxemapping (uniform light direction in tangentspace)
1389 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1390 permutation |= SHADERPERMUTATION_DIFFUSE;
1391 if (specularscale > 0)
1392 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1394 else if (rsurface.uselightmaptexture)
1396 // ordinary lightmapping (q1bsp, q3bsp)
1397 mode = SHADERMODE_LIGHTMAP;
1401 // ordinary vertex coloring (q3bsp)
1402 mode = SHADERMODE_VERTEXCOLOR;
1404 if (rsurface.texture->currentskinframe->glow)
1405 permutation |= SHADERPERMUTATION_GLOW;
1406 if (r_refdef.fogenabled)
1407 permutation |= SHADERPERMUTATION_FOG;
1408 if (rsurface.texture->colormapping)
1409 permutation |= SHADERPERMUTATION_COLORMAPPING;
1410 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1411 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1412 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1413 permutation |= SHADERPERMUTATION_REFLECTION;
1415 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1416 if (!r_glsl_permutation->program)
1418 if (!r_glsl_permutation->compiled)
1419 R_GLSL_CompilePermutation(mode, permutation);
1420 if (!r_glsl_permutation->program)
1422 // remove features until we find a valid permutation
1424 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1426 // reduce i more quickly whenever it would not remove any bits
1427 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1428 if (!(permutation & j))
1431 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1432 if (!r_glsl_permutation->compiled)
1433 R_GLSL_CompilePermutation(mode, permutation);
1434 if (r_glsl_permutation->program)
1437 if (i >= SHADERPERMUTATION_COUNT)
1439 Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n");
1440 Cvar_SetValueQuick(&r_glsl, 0);
1441 return 0; // no bit left to clear
1446 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1447 if (mode == SHADERMODE_LIGHTSOURCE)
1449 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1450 if (permutation & SHADERPERMUTATION_DIFFUSE)
1452 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1453 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1454 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1455 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1459 // ambient only is simpler
1460 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1461 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1462 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1463 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1466 else if (mode == SHADERMODE_LIGHTDIRECTION)
1468 if (r_glsl_permutation->loc_AmbientColor >= 0)
1469 qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale * rsurface.texture->lightmapcolor[0] * 0.5f, rsurface.modellight_ambient[1] * ambientscale * rsurface.texture->lightmapcolor[1] * 0.5f, rsurface.modellight_ambient[2] * ambientscale * rsurface.texture->lightmapcolor[2] * 0.5f);
1470 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1471 qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale * rsurface.texture->lightmapcolor[0] * 0.5f, rsurface.modellight_diffuse[1] * diffusescale * rsurface.texture->lightmapcolor[1] * 0.5f, rsurface.modellight_diffuse[2] * diffusescale * rsurface.texture->lightmapcolor[2] * 0.5f);
1472 if (r_glsl_permutation->loc_SpecularColor >= 0)
1473 qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * rsurface.texture->lightmapcolor[0] * 0.5f, rsurface.modellight_diffuse[1] * specularscale * rsurface.texture->lightmapcolor[1] * 0.5f, rsurface.modellight_diffuse[2] * specularscale * rsurface.texture->lightmapcolor[2] * 0.5f);
1474 if (r_glsl_permutation->loc_LightDir >= 0)
1475 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1479 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
1480 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1481 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1483 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]);
1484 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1485 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1487 // The formula used is actually:
1488 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1489 // color.rgb *= SceneBrightness;
1491 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1492 // and do [[calculations]] here in the engine
1493 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1494 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1497 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1498 if (r_glsl_permutation->loc_FogColor >= 0)
1500 // additive passes are only darkened by fog, not tinted
1501 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1502 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1504 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1506 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1507 if (r_glsl_permutation->loc_Color_Pants >= 0)
1509 if (rsurface.texture->currentskinframe->pants)
1510 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1512 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1514 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1516 if (rsurface.texture->currentskinframe->shirt)
1517 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1519 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1521 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1522 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1523 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1524 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
1525 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
1526 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
1527 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1528 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1529 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1530 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1535 #define SKINFRAME_HASH 1024
1539 int loadsequence; // incremented each level change
1540 memexpandablearray_t array;
1541 skinframe_t *hash[SKINFRAME_HASH];
1545 void R_SkinFrame_PrepareForPurge(void)
1547 r_skinframe.loadsequence++;
1548 // wrap it without hitting zero
1549 if (r_skinframe.loadsequence >= 200)
1550 r_skinframe.loadsequence = 1;
1553 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1557 // mark the skinframe as used for the purging code
1558 skinframe->loadsequence = r_skinframe.loadsequence;
1561 void R_SkinFrame_Purge(void)
1565 for (i = 0;i < SKINFRAME_HASH;i++)
1567 for (s = r_skinframe.hash[i];s;s = s->next)
1569 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1571 if (s->merged == s->base)
1573 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1574 R_PurgeTexture(s->stain );s->stain = NULL;
1575 R_PurgeTexture(s->merged);s->merged = NULL;
1576 R_PurgeTexture(s->base );s->base = NULL;
1577 R_PurgeTexture(s->pants );s->pants = NULL;
1578 R_PurgeTexture(s->shirt );s->shirt = NULL;
1579 R_PurgeTexture(s->nmap );s->nmap = NULL;
1580 R_PurgeTexture(s->gloss );s->gloss = NULL;
1581 R_PurgeTexture(s->glow );s->glow = NULL;
1582 R_PurgeTexture(s->fog );s->fog = NULL;
1583 s->loadsequence = 0;
1589 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1591 char basename[MAX_QPATH];
1593 Image_StripImageExtension(name, basename, sizeof(basename));
1595 if( last == NULL ) {
1597 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1598 item = r_skinframe.hash[hashindex];
1603 // linearly search through the hash bucket
1604 for( ; item ; item = item->next ) {
1605 if( !strcmp( item->basename, basename ) ) {
1612 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1616 char basename[MAX_QPATH];
1618 Image_StripImageExtension(name, basename, sizeof(basename));
1620 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1621 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1622 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1626 rtexture_t *dyntexture;
1627 // check whether its a dynamic texture
1628 dyntexture = CL_GetDynTexture( basename );
1629 if (!add && !dyntexture)
1631 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1632 memset(item, 0, sizeof(*item));
1633 strlcpy(item->basename, basename, sizeof(item->basename));
1634 item->base = dyntexture; // either NULL or dyntexture handle
1635 item->textureflags = textureflags;
1636 item->comparewidth = comparewidth;
1637 item->compareheight = compareheight;
1638 item->comparecrc = comparecrc;
1639 item->next = r_skinframe.hash[hashindex];
1640 r_skinframe.hash[hashindex] = item;
1642 else if( item->base == NULL )
1644 rtexture_t *dyntexture;
1645 // check whether its a dynamic texture
1646 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
1647 dyntexture = CL_GetDynTexture( basename );
1648 item->base = dyntexture; // either NULL or dyntexture handle
1651 R_SkinFrame_MarkUsed(item);
1655 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1657 // FIXME: it should be possible to disable loading various layers using
1658 // cvars, to prevent wasted loading time and memory usage if the user does
1660 qboolean loadnormalmap = true;
1661 qboolean loadgloss = true;
1662 qboolean loadpantsandshirt = true;
1663 qboolean loadglow = true;
1665 unsigned char *pixels;
1666 unsigned char *bumppixels;
1667 unsigned char *basepixels = NULL;
1668 int basepixels_width;
1669 int basepixels_height;
1670 skinframe_t *skinframe;
1672 if (cls.state == ca_dedicated)
1675 // return an existing skinframe if already loaded
1676 // if loading of the first image fails, don't make a new skinframe as it
1677 // would cause all future lookups of this to be missing
1678 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1679 if (skinframe && skinframe->base)
1682 basepixels = loadimagepixelsbgra(name, complain, true);
1683 if (basepixels == NULL)
1686 // we've got some pixels to store, so really allocate this new texture now
1688 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1689 skinframe->stain = NULL;
1690 skinframe->merged = NULL;
1691 skinframe->base = r_texture_notexture;
1692 skinframe->pants = NULL;
1693 skinframe->shirt = NULL;
1694 skinframe->nmap = r_texture_blanknormalmap;
1695 skinframe->gloss = NULL;
1696 skinframe->glow = NULL;
1697 skinframe->fog = NULL;
1699 basepixels_width = image_width;
1700 basepixels_height = image_height;
1701 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1703 if (textureflags & TEXF_ALPHA)
1705 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1706 if (basepixels[j] < 255)
1708 if (j < basepixels_width * basepixels_height * 4)
1710 // has transparent pixels
1711 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1712 for (j = 0;j < image_width * image_height * 4;j += 4)
1717 pixels[j+3] = basepixels[j+3];
1719 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1724 // _norm is the name used by tenebrae and has been adopted as standard
1727 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1729 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1733 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1735 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1736 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1737 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1739 Mem_Free(bumppixels);
1741 else if (r_shadow_bumpscale_basetexture.value > 0)
1743 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1744 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1745 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1749 // _luma is supported for tenebrae compatibility
1750 // (I think it's a very stupid name, but oh well)
1751 // _glow is the preferred name
1752 if (loadglow && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) != NULL || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1753 if (loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1754 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1755 if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1758 Mem_Free(basepixels);
1763 static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
1768 for (i = 0;i < width*height;i++)
1769 if (((unsigned char *)&palette[in[i]])[3] > 0)
1771 if (i == width*height)
1774 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1777 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
1778 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
1781 unsigned char *temp1, *temp2;
1782 skinframe_t *skinframe;
1784 if (cls.state == ca_dedicated)
1787 // if already loaded just return it, otherwise make a new skinframe
1788 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
1789 if (skinframe && skinframe->base)
1792 skinframe->stain = NULL;
1793 skinframe->merged = NULL;
1794 skinframe->base = r_texture_notexture;
1795 skinframe->pants = NULL;
1796 skinframe->shirt = NULL;
1797 skinframe->nmap = r_texture_blanknormalmap;
1798 skinframe->gloss = NULL;
1799 skinframe->glow = NULL;
1800 skinframe->fog = NULL;
1802 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1806 if (r_shadow_bumpscale_basetexture.value > 0)
1808 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1809 temp2 = temp1 + width * height * 4;
1810 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1811 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1814 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1815 if (textureflags & TEXF_ALPHA)
1817 for (i = 3;i < width * height * 4;i += 4)
1818 if (skindata[i] < 255)
1820 if (i < width * height * 4)
1822 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1823 memcpy(fogpixels, skindata, width * height * 4);
1824 for (i = 0;i < width * height * 4;i += 4)
1825 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1826 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1827 Mem_Free(fogpixels);
1834 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
1837 unsigned char *temp1, *temp2;
1838 skinframe_t *skinframe;
1840 if (cls.state == ca_dedicated)
1843 // if already loaded just return it, otherwise make a new skinframe
1844 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
1845 if (skinframe && skinframe->base)
1848 skinframe->stain = NULL;
1849 skinframe->merged = NULL;
1850 skinframe->base = r_texture_notexture;
1851 skinframe->pants = NULL;
1852 skinframe->shirt = NULL;
1853 skinframe->nmap = r_texture_blanknormalmap;
1854 skinframe->gloss = NULL;
1855 skinframe->glow = NULL;
1856 skinframe->fog = NULL;
1858 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1862 if (r_shadow_bumpscale_basetexture.value > 0)
1864 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1865 temp2 = temp1 + width * height * 4;
1866 // use either a custom palette or the quake palette
1867 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
1868 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1869 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1872 // use either a custom palette, or the quake palette
1873 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete)), skinframe->textureflags, true); // all
1874 if (loadglowtexture)
1875 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
1876 if (loadpantsandshirt)
1878 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
1879 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
1881 if (skinframe->pants || skinframe->shirt)
1882 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename), loadglowtexture ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap, skinframe->textureflags, false); // no special colors
1883 if (textureflags & TEXF_ALPHA)
1885 for (i = 0;i < width * height;i++)
1886 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
1888 if (i < width * height)
1889 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
1895 skinframe_t *R_SkinFrame_LoadMissing(void)
1897 skinframe_t *skinframe;
1899 if (cls.state == ca_dedicated)
1902 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1903 skinframe->stain = NULL;
1904 skinframe->merged = NULL;
1905 skinframe->base = r_texture_notexture;
1906 skinframe->pants = NULL;
1907 skinframe->shirt = NULL;
1908 skinframe->nmap = r_texture_blanknormalmap;
1909 skinframe->gloss = NULL;
1910 skinframe->glow = NULL;
1911 skinframe->fog = NULL;
1916 void gl_main_start(void)
1918 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1919 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1921 // set up r_skinframe loading system for textures
1922 memset(&r_skinframe, 0, sizeof(r_skinframe));
1923 r_skinframe.loadsequence = 1;
1924 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1926 r_main_texturepool = R_AllocTexturePool();
1927 R_BuildBlankTextures();
1929 if (gl_texturecubemap)
1932 R_BuildNormalizationCube();
1934 r_texture_fogattenuation = NULL;
1935 //r_texture_fogintensity = NULL;
1936 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1937 memset(&r_waterstate, 0, sizeof(r_waterstate));
1938 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1939 memset(&r_svbsp, 0, sizeof (r_svbsp));
1941 r_refdef.fogmasktable_density = 0;
1944 void gl_main_shutdown(void)
1946 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1947 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1949 // clear out the r_skinframe state
1950 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1951 memset(&r_skinframe, 0, sizeof(r_skinframe));
1954 Mem_Free(r_svbsp.nodes);
1955 memset(&r_svbsp, 0, sizeof (r_svbsp));
1956 R_FreeTexturePool(&r_main_texturepool);
1957 r_texture_blanknormalmap = NULL;
1958 r_texture_white = NULL;
1959 r_texture_grey128 = NULL;
1960 r_texture_black = NULL;
1961 r_texture_whitecube = NULL;
1962 r_texture_normalizationcube = NULL;
1963 r_texture_fogattenuation = NULL;
1964 //r_texture_fogintensity = NULL;
1965 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1966 memset(&r_waterstate, 0, sizeof(r_waterstate));
1970 extern void CL_ParseEntityLump(char *entitystring);
1971 void gl_main_newmap(void)
1973 // FIXME: move this code to client
1975 char *entities, entname[MAX_QPATH];
1978 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1979 l = (int)strlen(entname) - 4;
1980 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1982 memcpy(entname + l, ".ent", 5);
1983 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1985 CL_ParseEntityLump(entities);
1990 if (cl.worldmodel->brush.entities)
1991 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1995 void GL_Main_Init(void)
1997 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1999 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2000 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2001 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2002 if (gamemode == GAME_NEHAHRA)
2004 Cvar_RegisterVariable (&gl_fogenable);
2005 Cvar_RegisterVariable (&gl_fogdensity);
2006 Cvar_RegisterVariable (&gl_fogred);
2007 Cvar_RegisterVariable (&gl_foggreen);
2008 Cvar_RegisterVariable (&gl_fogblue);
2009 Cvar_RegisterVariable (&gl_fogstart);
2010 Cvar_RegisterVariable (&gl_fogend);
2011 Cvar_RegisterVariable (&gl_skyclip);
2013 Cvar_RegisterVariable(&r_depthfirst);
2014 Cvar_RegisterVariable(&r_nearclip);
2015 Cvar_RegisterVariable(&r_showbboxes);
2016 Cvar_RegisterVariable(&r_showsurfaces);
2017 Cvar_RegisterVariable(&r_showtris);
2018 Cvar_RegisterVariable(&r_shownormals);
2019 Cvar_RegisterVariable(&r_showlighting);
2020 Cvar_RegisterVariable(&r_showshadowvolumes);
2021 Cvar_RegisterVariable(&r_showcollisionbrushes);
2022 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2023 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2024 Cvar_RegisterVariable(&r_showdisabledepthtest);
2025 Cvar_RegisterVariable(&r_drawportals);
2026 Cvar_RegisterVariable(&r_drawentities);
2027 Cvar_RegisterVariable(&r_cullentities_trace);
2028 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2029 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2030 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2031 Cvar_RegisterVariable(&r_drawviewmodel);
2032 Cvar_RegisterVariable(&r_speeds);
2033 Cvar_RegisterVariable(&r_fullbrights);
2034 Cvar_RegisterVariable(&r_wateralpha);
2035 Cvar_RegisterVariable(&r_dynamic);
2036 Cvar_RegisterVariable(&r_fullbright);
2037 Cvar_RegisterVariable(&r_shadows);
2038 Cvar_RegisterVariable(&r_shadows_throwdistance);
2039 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2040 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2041 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2042 Cvar_RegisterVariable(&r_fog_exp2);
2043 Cvar_RegisterVariable(&r_textureunits);
2044 Cvar_RegisterVariable(&r_glsl);
2045 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2046 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2047 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2048 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2049 Cvar_RegisterVariable(&r_water);
2050 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2051 Cvar_RegisterVariable(&r_water_clippingplanebias);
2052 Cvar_RegisterVariable(&r_water_refractdistort);
2053 Cvar_RegisterVariable(&r_water_reflectdistort);
2054 Cvar_RegisterVariable(&r_lerpsprites);
2055 Cvar_RegisterVariable(&r_lerpmodels);
2056 Cvar_RegisterVariable(&r_lerplightstyles);
2057 Cvar_RegisterVariable(&r_waterscroll);
2058 Cvar_RegisterVariable(&r_bloom);
2059 Cvar_RegisterVariable(&r_bloom_colorscale);
2060 Cvar_RegisterVariable(&r_bloom_brighten);
2061 Cvar_RegisterVariable(&r_bloom_blur);
2062 Cvar_RegisterVariable(&r_bloom_resolution);
2063 Cvar_RegisterVariable(&r_bloom_colorexponent);
2064 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2065 Cvar_RegisterVariable(&r_hdr);
2066 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2067 Cvar_RegisterVariable(&r_glsl_contrastboost);
2068 Cvar_RegisterVariable(&r_hdr_glowintensity);
2069 Cvar_RegisterVariable(&r_hdr_range);
2070 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2071 Cvar_RegisterVariable(&developer_texturelogging);
2072 Cvar_RegisterVariable(&gl_lightmaps);
2073 Cvar_RegisterVariable(&r_test);
2074 Cvar_RegisterVariable(&r_batchmode);
2075 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2076 Cvar_SetValue("r_fullbrights", 0);
2077 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2079 Cvar_RegisterVariable(&r_track_sprites);
2080 Cvar_RegisterVariable(&r_track_sprites_flags);
2081 Cvar_RegisterVariable(&r_track_sprites_scalew);
2082 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2085 extern void R_Textures_Init(void);
2086 extern void GL_Draw_Init(void);
2087 extern void GL_Main_Init(void);
2088 extern void R_Shadow_Init(void);
2089 extern void R_Sky_Init(void);
2090 extern void GL_Surf_Init(void);
2091 extern void R_Particles_Init(void);
2092 extern void R_Explosion_Init(void);
2093 extern void gl_backend_init(void);
2094 extern void Sbar_Init(void);
2095 extern void R_LightningBeams_Init(void);
2096 extern void Mod_RenderInit(void);
2098 void Render_Init(void)
2110 R_LightningBeams_Init();
2119 extern char *ENGINE_EXTENSIONS;
2122 VID_CheckExtensions();
2124 // LordHavoc: report supported extensions
2125 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2127 // clear to black (loading plaque will be seen over this)
2129 qglClearColor(0,0,0,1);CHECKGLERROR
2130 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2133 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2137 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2139 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2142 p = r_refdef.view.frustum + i;
2147 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2151 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2155 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2159 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2163 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2167 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2171 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2175 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2183 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2187 for (i = 0;i < numplanes;i++)
2194 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2198 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2202 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2206 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2210 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2214 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2218 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2222 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2230 //==================================================================================
2232 static void R_View_UpdateEntityVisible (void)
2235 entity_render_t *ent;
2237 if (!r_drawentities.integer)
2240 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2241 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2243 // worldmodel can check visibility
2244 for (i = 0;i < r_refdef.scene.numentities;i++)
2246 ent = r_refdef.scene.entities[i];
2247 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs));
2250 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2252 for (i = 0;i < r_refdef.scene.numentities;i++)
2254 ent = r_refdef.scene.entities[i];
2255 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2257 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.scene.worldmodel, r_refdef.view.origin, ent->mins, ent->maxs))
2258 ent->last_trace_visibility = realtime;
2259 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2260 r_refdef.viewcache.entityvisible[i] = 0;
2267 // no worldmodel or it can't check visibility
2268 for (i = 0;i < r_refdef.scene.numentities;i++)
2270 ent = r_refdef.scene.entities[i];
2271 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
2276 // only used if skyrendermasked, and normally returns false
2277 int R_DrawBrushModelsSky (void)
2280 entity_render_t *ent;
2282 if (!r_drawentities.integer)
2286 for (i = 0;i < r_refdef.scene.numentities;i++)
2288 if (!r_refdef.viewcache.entityvisible[i])
2290 ent = r_refdef.scene.entities[i];
2291 if (!ent->model || !ent->model->DrawSky)
2293 ent->model->DrawSky(ent);
2299 static void R_DrawNoModel(entity_render_t *ent);
2300 static void R_DrawModels(void)
2303 entity_render_t *ent;
2305 if (!r_drawentities.integer)
2308 for (i = 0;i < r_refdef.scene.numentities;i++)
2310 if (!r_refdef.viewcache.entityvisible[i])
2312 ent = r_refdef.scene.entities[i];
2313 r_refdef.stats.entities++;
2314 if (ent->model && ent->model->Draw != NULL)
2315 ent->model->Draw(ent);
2321 static void R_DrawModelsDepth(void)
2324 entity_render_t *ent;
2326 if (!r_drawentities.integer)
2329 for (i = 0;i < r_refdef.scene.numentities;i++)
2331 if (!r_refdef.viewcache.entityvisible[i])
2333 ent = r_refdef.scene.entities[i];
2334 if (ent->model && ent->model->DrawDepth != NULL)
2335 ent->model->DrawDepth(ent);
2339 static void R_DrawModelsDebug(void)
2342 entity_render_t *ent;
2344 if (!r_drawentities.integer)
2347 for (i = 0;i < r_refdef.scene.numentities;i++)
2349 if (!r_refdef.viewcache.entityvisible[i])
2351 ent = r_refdef.scene.entities[i];
2352 if (ent->model && ent->model->DrawDebug != NULL)
2353 ent->model->DrawDebug(ent);
2357 static void R_DrawModelsAddWaterPlanes(void)
2360 entity_render_t *ent;
2362 if (!r_drawentities.integer)
2365 for (i = 0;i < r_refdef.scene.numentities;i++)
2367 if (!r_refdef.viewcache.entityvisible[i])
2369 ent = r_refdef.scene.entities[i];
2370 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2371 ent->model->DrawAddWaterPlanes(ent);
2375 static void R_View_SetFrustum(void)
2378 double slopex, slopey;
2380 // break apart the view matrix into vectors for various purposes
2381 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
2382 VectorNegate(r_refdef.view.left, r_refdef.view.right);
2385 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2386 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2387 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2388 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2389 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2390 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2391 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2392 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2393 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2394 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2395 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2396 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2400 zNear = r_refdef.nearclip;
2401 nudge = 1.0 - 1.0 / (1<<23);
2402 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2403 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2404 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2405 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2406 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2407 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2408 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2409 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2415 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2416 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2417 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2418 r_refdef.view.frustum[0].dist = m[15] - m[12];
2420 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2421 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2422 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2423 r_refdef.view.frustum[1].dist = m[15] + m[12];
2425 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2426 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2427 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2428 r_refdef.view.frustum[2].dist = m[15] - m[13];
2430 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2431 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2432 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2433 r_refdef.view.frustum[3].dist = m[15] + m[13];
2435 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2436 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2437 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2438 r_refdef.view.frustum[4].dist = m[15] - m[14];
2440 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2441 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2442 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2443 r_refdef.view.frustum[5].dist = m[15] + m[14];
2446 if (r_refdef.view.useperspective)
2448 slopex = 1.0 / r_refdef.view.frustum_x;
2449 slopey = 1.0 / r_refdef.view.frustum_y;
2450 VectorMA(r_refdef.view.forward, -slopex, r_refdef.view.left, r_refdef.view.frustum[0].normal);
2451 VectorMA(r_refdef.view.forward, slopex, r_refdef.view.left, r_refdef.view.frustum[1].normal);
2452 VectorMA(r_refdef.view.forward, -slopey, r_refdef.view.up , r_refdef.view.frustum[2].normal);
2453 VectorMA(r_refdef.view.forward, slopey, r_refdef.view.up , r_refdef.view.frustum[3].normal);
2454 VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
2456 // Leaving those out was a mistake, those were in the old code, and they
2457 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2458 // I couldn't reproduce it after adding those normalizations. --blub
2459 VectorNormalize(r_refdef.view.frustum[0].normal);
2460 VectorNormalize(r_refdef.view.frustum[1].normal);
2461 VectorNormalize(r_refdef.view.frustum[2].normal);
2462 VectorNormalize(r_refdef.view.frustum[3].normal);
2464 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2465 VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, -1024 * slopex, r_refdef.view.left, -1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[0]);
2466 VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, 1024 * slopex, r_refdef.view.left, -1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[1]);
2467 VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, -1024 * slopex, r_refdef.view.left, 1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[2]);
2468 VectorMAMAMAM(1, r_refdef.view.origin, 1024, r_refdef.view.forward, 1024 * slopex, r_refdef.view.left, 1024 * slopey, r_refdef.view.up, r_refdef.view.frustumcorner[3]);
2470 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2471 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2472 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2473 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2474 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2478 VectorScale(r_refdef.view.left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2479 VectorScale(r_refdef.view.left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2480 VectorScale(r_refdef.view.up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2481 VectorScale(r_refdef.view.up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2482 VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
2483 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2484 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2485 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2486 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2487 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2489 r_refdef.view.numfrustumplanes = 5;
2491 if (r_refdef.view.useclipplane)
2493 r_refdef.view.numfrustumplanes = 6;
2494 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2497 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2498 PlaneClassify(r_refdef.view.frustum + i);
2500 // LordHavoc: note to all quake engine coders, Quake had a special case
2501 // for 90 degrees which assumed a square view (wrong), so I removed it,
2502 // Quake2 has it disabled as well.
2504 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2505 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, r_refdef.view.up, r_refdef.view.forward, -(90 - r_refdef.fov_x / 2));
2506 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2507 //PlaneClassify(&frustum[0]);
2509 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2510 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, r_refdef.view.up, r_refdef.view.forward, (90 - r_refdef.fov_x / 2));
2511 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2512 //PlaneClassify(&frustum[1]);
2514 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2515 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, r_refdef.view.left, r_refdef.view.forward, -(90 - r_refdef.fov_y / 2));
2516 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2517 //PlaneClassify(&frustum[2]);
2519 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2520 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, r_refdef.view.left, r_refdef.view.forward, (90 - r_refdef.fov_y / 2));
2521 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2522 //PlaneClassify(&frustum[3]);
2525 //VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
2526 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2527 //PlaneClassify(&frustum[4]);
2530 void R_View_Update(void)
2532 R_View_SetFrustum();
2533 R_View_WorldVisibility(r_refdef.view.useclipplane);
2534 R_View_UpdateEntityVisible();
2537 void R_SetupView(void)
2539 if (!r_refdef.view.useperspective)
2540 GL_SetupView_Mode_Ortho(-r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
2541 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2542 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2544 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2546 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2548 if (r_refdef.view.useclipplane)
2550 // LordHavoc: couldn't figure out how to make this approach the
2551 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2552 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2553 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2554 dist = r_refdef.view.clipplane.dist;
2555 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2559 void R_ResetViewRendering2D(void)
2561 if (gl_support_fragment_shader)
2563 qglUseProgramObjectARB(0);CHECKGLERROR
2568 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2569 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2570 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2571 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2572 GL_Color(1, 1, 1, 1);
2573 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2574 GL_BlendFunc(GL_ONE, GL_ZERO);
2575 GL_AlphaTest(false);
2576 GL_ScissorTest(false);
2577 GL_DepthMask(false);
2578 GL_DepthRange(0, 1);
2579 GL_DepthTest(false);
2580 R_Mesh_Matrix(&identitymatrix);
2581 R_Mesh_ResetTextureState();
2582 GL_PolygonOffset(0, 0);
2583 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2584 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2585 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2586 qglStencilMask(~0);CHECKGLERROR
2587 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2588 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2589 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2592 void R_ResetViewRendering3D(void)
2594 if (gl_support_fragment_shader)
2596 qglUseProgramObjectARB(0);CHECKGLERROR
2601 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2602 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2604 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2605 GL_Color(1, 1, 1, 1);
2606 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2607 GL_BlendFunc(GL_ONE, GL_ZERO);
2608 GL_AlphaTest(false);
2609 GL_ScissorTest(true);
2611 GL_DepthRange(0, 1);
2613 R_Mesh_Matrix(&identitymatrix);
2614 R_Mesh_ResetTextureState();
2615 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2616 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2617 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2618 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2619 qglStencilMask(~0);CHECKGLERROR
2620 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2621 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2622 GL_CullFace(r_refdef.view.cullface_back);
2626 R_Bloom_SetupShader(
2628 "// written by Forest 'LordHavoc' Hale\n"
2630 "// common definitions between vertex shader and fragment shader:\n"
2632 "#ifdef __GLSL_CG_DATA_TYPES\n"
2633 "#define myhalf half\n"
2634 "#define myhalf2 half2\n"
2635 "#define myhalf3 half3\n"
2636 "#define myhalf4 half4\n"
2638 "#define myhalf float\n"
2639 "#define myhalf2 vec2\n"
2640 "#define myhalf3 vec3\n"
2641 "#define myhalf4 vec4\n"
2644 "varying vec2 ScreenTexCoord;\n"
2645 "varying vec2 BloomTexCoord;\n"
2650 "// vertex shader specific:\n"
2651 "#ifdef VERTEX_SHADER\n"
2655 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2656 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2657 " // transform vertex to camera space, using ftransform to match non-VS\n"
2659 " gl_Position = ftransform();\n"
2662 "#endif // VERTEX_SHADER\n"
2667 "// fragment shader specific:\n"
2668 "#ifdef FRAGMENT_SHADER\n"
2673 " myhalf3 color = myhalf3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2674 " for (x = -BLUR_X;x <= BLUR_X;x++)
2675 " color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2676 " color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2677 " color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2678 " color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2680 " gl_FragColor = vec4(color);\n"
2683 "#endif // FRAGMENT_SHADER\n"
2686 void R_RenderScene(qboolean addwaterplanes);
2688 static void R_Water_StartFrame(void)
2691 int waterwidth, waterheight, texturewidth, textureheight;
2692 r_waterstate_waterplane_t *p;
2694 // set waterwidth and waterheight to the water resolution that will be
2695 // used (often less than the screen resolution for faster rendering)
2696 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
2697 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
2699 // calculate desired texture sizes
2700 // can't use water if the card does not support the texture size
2701 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2702 texturewidth = textureheight = waterwidth = waterheight = 0;
2703 else if (gl_support_arb_texture_non_power_of_two)
2705 texturewidth = waterwidth;
2706 textureheight = waterheight;
2710 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2711 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2714 // allocate textures as needed
2715 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2717 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2718 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2720 if (p->texture_refraction)
2721 R_FreeTexture(p->texture_refraction);
2722 p->texture_refraction = NULL;
2723 if (p->texture_reflection)
2724 R_FreeTexture(p->texture_reflection);
2725 p->texture_reflection = NULL;
2727 memset(&r_waterstate, 0, sizeof(r_waterstate));
2728 r_waterstate.waterwidth = waterwidth;
2729 r_waterstate.waterheight = waterheight;
2730 r_waterstate.texturewidth = texturewidth;
2731 r_waterstate.textureheight = textureheight;
2734 if (r_waterstate.waterwidth)
2736 r_waterstate.enabled = true;
2738 // set up variables that will be used in shader setup
2739 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2740 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2741 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2742 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2745 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2746 r_waterstate.numwaterplanes = 0;
2749 static void R_Water_AddWaterPlane(msurface_t *surface)
2751 int triangleindex, planeindex;
2756 r_waterstate_waterplane_t *p;
2757 // just use the first triangle with a valid normal for any decisions
2758 VectorClear(normal);
2759 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2761 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2762 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2763 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2764 TriangleNormal(vert[0], vert[1], vert[2], normal);
2765 if (VectorLength2(normal) >= 0.001)
2769 // find a matching plane if there is one
2770 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2771 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2773 if (planeindex >= r_waterstate.maxwaterplanes)
2774 return; // nothing we can do, out of planes
2776 // if this triangle does not fit any known plane rendered this frame, add one
2777 if (planeindex >= r_waterstate.numwaterplanes)
2779 // store the new plane
2780 r_waterstate.numwaterplanes++;
2781 VectorCopy(normal, p->plane.normal);
2782 VectorNormalize(p->plane.normal);
2783 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2784 PlaneClassify(&p->plane);
2785 // flip the plane if it does not face the viewer
2786 if (PlaneDiff(r_refdef.view.origin, &p->plane) < 0)
2788 VectorNegate(p->plane.normal, p->plane.normal);
2789 p->plane.dist *= -1;
2790 PlaneClassify(&p->plane);
2792 // clear materialflags and pvs
2793 p->materialflags = 0;
2794 p->pvsvalid = false;
2796 // merge this surface's materialflags into the waterplane
2797 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2798 // merge this surface's PVS into the waterplane
2799 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
2800 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
2801 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
2803 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2808 static void R_Water_ProcessPlanes(void)
2810 r_refdef_view_t originalview;
2812 r_waterstate_waterplane_t *p;
2814 originalview = r_refdef.view;
2816 // make sure enough textures are allocated
2817 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2819 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2821 if (!p->texture_refraction)
2822 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2823 if (!p->texture_refraction)
2827 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2829 if (!p->texture_reflection)
2830 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2831 if (!p->texture_reflection)
2837 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2839 r_refdef.view.showdebug = false;
2840 r_refdef.view.width = r_waterstate.waterwidth;
2841 r_refdef.view.height = r_waterstate.waterheight;
2842 r_refdef.view.useclipplane = true;
2843 r_waterstate.renderingscene = true;
2845 // render the normal view scene and copy into texture
2846 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
2847 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2849 r_refdef.view.clipplane = p->plane;
2850 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
2851 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
2852 PlaneClassify(&r_refdef.view.clipplane);
2854 R_RenderScene(false);
2856 // copy view into the screen texture
2857 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2858 GL_ActiveTexture(0);
2860 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2863 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2865 // render reflected scene and copy into texture
2866 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2867 r_refdef.view.clipplane = p->plane;
2868 // reverse the cullface settings for this render
2869 r_refdef.view.cullface_front = GL_FRONT;
2870 r_refdef.view.cullface_back = GL_BACK;
2871 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
2873 r_refdef.view.usecustompvs = true;
2875 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
2877 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
2880 R_ResetViewRendering3D();
2881 R_ClearScreen(r_refdef.fogenabled);
2882 if (r_timereport_active)
2883 R_TimeReport("viewclear");
2885 R_RenderScene(false);
2887 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2888 GL_ActiveTexture(0);
2890 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2892 R_ResetViewRendering3D();
2893 R_ClearScreen(r_refdef.fogenabled);
2894 if (r_timereport_active)
2895 R_TimeReport("viewclear");
2898 r_refdef.view = originalview;
2899 r_refdef.view.clear = true;
2900 r_waterstate.renderingscene = false;
2904 r_refdef.view = originalview;
2905 r_waterstate.renderingscene = false;
2906 Cvar_SetValueQuick(&r_water, 0);
2907 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
2911 void R_Bloom_StartFrame(void)
2913 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2915 // set bloomwidth and bloomheight to the bloom resolution that will be
2916 // used (often less than the screen resolution for faster rendering)
2917 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
2918 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
2919 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
2921 // calculate desired texture sizes
2922 if (gl_support_arb_texture_non_power_of_two)
2924 screentexturewidth = r_refdef.view.width;
2925 screentextureheight = r_refdef.view.height;
2926 bloomtexturewidth = r_bloomstate.bloomwidth;
2927 bloomtextureheight = r_bloomstate.bloomheight;
2931 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2932 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2933 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2934 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2939 screentexturewidth = screentextureheight = 0;
2941 else if (r_bloom.integer)
2946 screentexturewidth = screentextureheight = 0;
2947 bloomtexturewidth = bloomtextureheight = 0;
2950 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)
2952 // can't use bloom if the parameters are too weird
2953 // can't use bloom if the card does not support the texture size
2954 if (r_bloomstate.texture_screen)
2955 R_FreeTexture(r_bloomstate.texture_screen);
2956 if (r_bloomstate.texture_bloom)
2957 R_FreeTexture(r_bloomstate.texture_bloom);
2958 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2962 r_bloomstate.enabled = true;
2963 r_bloomstate.hdr = r_hdr.integer != 0;
2965 // allocate textures as needed
2966 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2968 if (r_bloomstate.texture_screen)
2969 R_FreeTexture(r_bloomstate.texture_screen);
2970 r_bloomstate.texture_screen = NULL;
2971 r_bloomstate.screentexturewidth = screentexturewidth;
2972 r_bloomstate.screentextureheight = screentextureheight;
2973 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2974 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2976 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2978 if (r_bloomstate.texture_bloom)
2979 R_FreeTexture(r_bloomstate.texture_bloom);
2980 r_bloomstate.texture_bloom = NULL;
2981 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2982 r_bloomstate.bloomtextureheight = bloomtextureheight;
2983 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2984 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2987 // set up a texcoord array for the full resolution screen image
2988 // (we have to keep this around to copy back during final render)
2989 r_bloomstate.screentexcoord2f[0] = 0;
2990 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
2991 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
2992 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
2993 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
2994 r_bloomstate.screentexcoord2f[5] = 0;
2995 r_bloomstate.screentexcoord2f[6] = 0;
2996 r_bloomstate.screentexcoord2f[7] = 0;
2998 // set up a texcoord array for the reduced resolution bloom image
2999 // (which will be additive blended over the screen image)
3000 r_bloomstate.bloomtexcoord2f[0] = 0;
3001 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3002 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3003 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3004 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3005 r_bloomstate.bloomtexcoord2f[5] = 0;
3006 r_bloomstate.bloomtexcoord2f[6] = 0;
3007 r_bloomstate.bloomtexcoord2f[7] = 0;
3010 void R_Bloom_CopyScreenTexture(float colorscale)
3012 r_refdef.stats.bloom++;
3014 R_ResetViewRendering2D();
3015 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3016 R_Mesh_ColorPointer(NULL, 0, 0);
3017 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3018 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3020 // copy view into the screen texture
3021 GL_ActiveTexture(0);
3023 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3024 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3026 // now scale it down to the bloom texture size
3028 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3029 GL_BlendFunc(GL_ONE, GL_ZERO);
3030 GL_Color(colorscale, colorscale, colorscale, 1);
3031 // TODO: optimize with multitexture or GLSL
3032 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3033 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3035 // we now have a bloom image in the framebuffer
3036 // copy it into the bloom image texture for later processing
3037 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3038 GL_ActiveTexture(0);
3040 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3041 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3044 void R_Bloom_CopyHDRTexture(void)
3046 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3047 GL_ActiveTexture(0);
3049 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3050 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3053 void R_Bloom_MakeTexture(void)
3056 float xoffset, yoffset, r, brighten;
3058 r_refdef.stats.bloom++;
3060 R_ResetViewRendering2D();
3061 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3062 R_Mesh_ColorPointer(NULL, 0, 0);
3064 // we have a bloom image in the framebuffer
3066 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3068 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3071 r = bound(0, r_bloom_colorexponent.value / x, 1);
3072 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3073 GL_Color(r, r, r, 1);
3074 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3075 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3076 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3077 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3079 // copy the vertically blurred bloom view to a texture
3080 GL_ActiveTexture(0);
3082 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3083 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3086 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3087 brighten = r_bloom_brighten.value;
3089 brighten *= r_hdr_range.value;
3090 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3091 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3093 for (dir = 0;dir < 2;dir++)
3095 // blend on at multiple vertical offsets to achieve a vertical blur
3096 // TODO: do offset blends using GLSL
3097 GL_BlendFunc(GL_ONE, GL_ZERO);
3098 for (x = -range;x <= range;x++)
3100 if (!dir){xoffset = 0;yoffset = x;}
3101 else {xoffset = x;yoffset = 0;}
3102 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3103 yoffset /= (float)r_bloomstate.bloomtextureheight;
3104 // compute a texcoord array with the specified x and y offset
3105 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3106 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3107 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3108 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3109 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3110 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3111 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3112 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3113 // this r value looks like a 'dot' particle, fading sharply to
3114 // black at the edges
3115 // (probably not realistic but looks good enough)
3116 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3117 //r = (dir ? 1.0f : brighten)/(range*2+1);
3118 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3119 GL_Color(r, r, r, 1);
3120 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3121 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3122 GL_BlendFunc(GL_ONE, GL_ONE);
3125 // copy the vertically blurred bloom view to a texture
3126 GL_ActiveTexture(0);
3128 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3129 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3132 // apply subtract last
3133 // (just like it would be in a GLSL shader)
3134 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3136 GL_BlendFunc(GL_ONE, GL_ZERO);
3137 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3138 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3139 GL_Color(1, 1, 1, 1);
3140 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3141 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3143 GL_BlendFunc(GL_ONE, GL_ONE);
3144 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3145 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3146 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3147 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3148 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3149 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3150 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3152 // copy the darkened bloom view to a texture
3153 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3154 GL_ActiveTexture(0);
3156 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3157 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3161 void R_HDR_RenderBloomTexture(void)
3163 int oldwidth, oldheight;
3164 float oldcolorscale;
3166 oldcolorscale = r_refdef.view.colorscale;
3167 oldwidth = r_refdef.view.width;
3168 oldheight = r_refdef.view.height;
3169 r_refdef.view.width = r_bloomstate.bloomwidth;
3170 r_refdef.view.height = r_bloomstate.bloomheight;
3172 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3173 // TODO: add exposure compensation features
3174 // TODO: add fp16 framebuffer support
3176 r_refdef.view.showdebug = false;
3177 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3179 R_ClearScreen(r_refdef.fogenabled);
3180 if (r_timereport_active)
3181 R_TimeReport("HDRclear");
3183 r_waterstate.numwaterplanes = 0;
3184 R_RenderScene(r_waterstate.enabled);
3185 r_refdef.view.showdebug = true;
3187 R_ResetViewRendering2D();
3189 R_Bloom_CopyHDRTexture();
3190 R_Bloom_MakeTexture();
3192 // restore the view settings
3193 r_refdef.view.width = oldwidth;
3194 r_refdef.view.height = oldheight;
3195 r_refdef.view.colorscale = oldcolorscale;
3197 R_ResetViewRendering3D();
3199 R_ClearScreen(r_refdef.fogenabled);
3200 if (r_timereport_active)
3201 R_TimeReport("viewclear");
3204 static void R_BlendView(void)
3206 if (r_bloomstate.enabled && r_bloomstate.hdr)
3208 // render high dynamic range bloom effect
3209 // the bloom texture was made earlier this render, so we just need to
3210 // blend it onto the screen...
3211 R_ResetViewRendering2D();
3212 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3213 R_Mesh_ColorPointer(NULL, 0, 0);
3214 GL_Color(1, 1, 1, 1);
3215 GL_BlendFunc(GL_ONE, GL_ONE);
3216 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3217 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3218 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3219 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3221 else if (r_bloomstate.enabled)
3223 // render simple bloom effect
3224 // copy the screen and shrink it and darken it for the bloom process
3225 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
3226 // make the bloom texture
3227 R_Bloom_MakeTexture();
3228 // put the original screen image back in place and blend the bloom
3230 R_ResetViewRendering2D();
3231 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3232 R_Mesh_ColorPointer(NULL, 0, 0);
3233 GL_Color(1, 1, 1, 1);
3234 GL_BlendFunc(GL_ONE, GL_ZERO);
3235 // do both in one pass if possible
3236 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3237 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3238 if (r_textureunits.integer >= 2 && gl_combine.integer)
3240 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
3241 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3242 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3246 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3247 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3248 // now blend on the bloom texture
3249 GL_BlendFunc(GL_ONE, GL_ONE);
3250 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3251 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3253 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3254 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3256 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3258 // apply a color tint to the whole view
3259 R_ResetViewRendering2D();
3260 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3261 R_Mesh_ColorPointer(NULL, 0, 0);
3262 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3263 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3264 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3268 void R_RenderScene(qboolean addwaterplanes);
3270 matrix4x4_t r_waterscrollmatrix;
3272 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3274 if (r_refdef.fog_density)
3276 r_refdef.fogcolor[0] = r_refdef.fog_red;
3277 r_refdef.fogcolor[1] = r_refdef.fog_green;
3278 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3282 VectorCopy(r_refdef.fogcolor, fogvec);
3283 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3285 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3286 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3287 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3288 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3290 // color.rgb *= ContrastBoost * SceneBrightness;
3291 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3292 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3293 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3294 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3299 void R_UpdateVariables(void)
3303 r_refdef.farclip = 4096;
3304 if (r_refdef.scene.worldmodel)
3305 r_refdef.farclip += VectorDistance(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3306 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3308 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3309 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3310 r_refdef.polygonfactor = 0;
3311 r_refdef.polygonoffset = 0;
3312 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3313 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3315 r_refdef.rtworld = r_shadow_realtime_world.integer;
3316 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3317 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3318 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3319 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3320 if (r_showsurfaces.integer)
3322 r_refdef.rtworld = false;
3323 r_refdef.rtworldshadows = false;
3324 r_refdef.rtdlight = false;
3325 r_refdef.rtdlightshadows = false;
3326 r_refdef.lightmapintensity = 0;
3329 if (gamemode == GAME_NEHAHRA)
3331 if (gl_fogenable.integer)
3333 r_refdef.oldgl_fogenable = true;
3334 r_refdef.fog_density = gl_fogdensity.value;
3335 r_refdef.fog_red = gl_fogred.value;
3336 r_refdef.fog_green = gl_foggreen.value;
3337 r_refdef.fog_blue = gl_fogblue.value;
3338 r_refdef.fog_alpha = 1;
3339 r_refdef.fog_start = 0;
3340 r_refdef.fog_end = gl_skyclip.value;
3342 else if (r_refdef.oldgl_fogenable)
3344 r_refdef.oldgl_fogenable = false;
3345 r_refdef.fog_density = 0;
3346 r_refdef.fog_red = 0;
3347 r_refdef.fog_green = 0;
3348 r_refdef.fog_blue = 0;
3349 r_refdef.fog_alpha = 0;
3350 r_refdef.fog_start = 0;
3351 r_refdef.fog_end = 0;
3355 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3356 r_refdef.fog_start = max(0, r_refdef.fog_start);
3357 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3359 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3361 if (r_refdef.fog_density)
3363 r_refdef.fogenabled = true;
3364 // this is the point where the fog reaches 0.9986 alpha, which we
3365 // consider a good enough cutoff point for the texture
3366 // (0.9986 * 256 == 255.6)
3367 if (r_fog_exp2.integer)
3368 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3370 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3371 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3372 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3373 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3374 // fog color was already set
3375 // update the fog texture
3376 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
3377 R_BuildFogTexture();
3380 r_refdef.fogenabled = false;
3388 void R_RenderView(void)
3390 if (!r_refdef.scene.entities/* || !r_refdef.scene.worldmodel*/)
3391 return; //Host_Error ("R_RenderView: NULL worldmodel");
3393 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3395 R_Shadow_UpdateWorldLightSelection();
3397 R_Bloom_StartFrame();
3398 R_Water_StartFrame();
3401 if (r_timereport_active)
3402 R_TimeReport("viewsetup");
3404 R_ResetViewRendering3D();
3406 if (r_refdef.view.clear || r_refdef.fogenabled)
3408 R_ClearScreen(r_refdef.fogenabled);
3409 if (r_timereport_active)
3410 R_TimeReport("viewclear");
3412 r_refdef.view.clear = true;
3414 r_refdef.view.showdebug = true;
3416 // this produces a bloom texture to be used in R_BlendView() later
3418 R_HDR_RenderBloomTexture();
3420 r_waterstate.numwaterplanes = 0;
3421 R_RenderScene(r_waterstate.enabled);
3424 if (r_timereport_active)
3425 R_TimeReport("blendview");
3427 GL_Scissor(0, 0, vid.width, vid.height);
3428 GL_ScissorTest(false);
3432 extern void R_DrawLightningBeams (void);
3433 extern void VM_CL_AddPolygonsToMeshQueue (void);
3434 extern void R_DrawPortals (void);
3435 extern cvar_t cl_locs_show;
3436 static void R_DrawLocs(void);
3437 static void R_DrawEntityBBoxes(void);
3438 void R_RenderScene(qboolean addwaterplanes)
3440 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3445 R_ResetViewRendering3D();
3448 if (r_timereport_active)
3449 R_TimeReport("watervis");
3451 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3453 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3454 if (r_timereport_active)
3455 R_TimeReport("waterworld");
3458 // don't let sound skip if going slow
3459 if (r_refdef.scene.extraupdate)
3462 R_DrawModelsAddWaterPlanes();
3463 if (r_timereport_active)
3464 R_TimeReport("watermodels");
3466 R_Water_ProcessPlanes();
3467 if (r_timereport_active)
3468 R_TimeReport("waterscenes");
3471 R_ResetViewRendering3D();
3473 // don't let sound skip if going slow
3474 if (r_refdef.scene.extraupdate)
3477 R_MeshQueue_BeginScene();
3482 if (r_timereport_active)
3483 R_TimeReport("visibility");
3485 Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
3487 if (cl.csqc_vidvars.drawworld)
3489 // don't let sound skip if going slow
3490 if (r_refdef.scene.extraupdate)
3493 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
3495 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
3496 if (r_timereport_active)
3497 R_TimeReport("worldsky");
3500 if (R_DrawBrushModelsSky() && r_timereport_active)
3501 R_TimeReport("bmodelsky");
3504 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
3506 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
3507 if (r_timereport_active)
3508 R_TimeReport("worlddepth");
3510 if (r_depthfirst.integer >= 2)
3512 R_DrawModelsDepth();
3513 if (r_timereport_active)
3514 R_TimeReport("modeldepth");
3517 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
3519 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
3520 if (r_timereport_active)
3521 R_TimeReport("world");
3524 // don't let sound skip if going slow
3525 if (r_refdef.scene.extraupdate)
3529 if (r_timereport_active)
3530 R_TimeReport("models");
3532 // don't let sound skip if going slow
3533 if (r_refdef.scene.extraupdate)
3536 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3538 R_DrawModelShadows();
3540 R_ResetViewRendering3D();
3542 // don't let sound skip if going slow
3543 if (r_refdef.scene.extraupdate)
3547 R_ShadowVolumeLighting(false);
3548 if (r_timereport_active)
3549 R_TimeReport("rtlights");
3551 // don't let sound skip if going slow
3552 if (r_refdef.scene.extraupdate)
3555 if (cl.csqc_vidvars.drawworld)
3557 R_DrawLightningBeams();
3558 if (r_timereport_active)
3559 R_TimeReport("lightning");
3562 if (r_timereport_active)
3563 R_TimeReport("decals");
3566 if (r_timereport_active)
3567 R_TimeReport("particles");
3570 if (r_timereport_active)
3571 R_TimeReport("explosions");
3574 if (gl_support_fragment_shader)
3576 qglUseProgramObjectARB(0);CHECKGLERROR
3578 VM_CL_AddPolygonsToMeshQueue();
3580 if (r_refdef.view.showdebug)
3582 if (cl_locs_show.integer)
3585 if (r_timereport_active)
3586 R_TimeReport("showlocs");
3589 if (r_drawportals.integer)
3592 if (r_timereport_active)
3593 R_TimeReport("portals");
3596 if (r_showbboxes.value > 0)
3598 R_DrawEntityBBoxes();
3599 if (r_timereport_active)
3600 R_TimeReport("bboxes");
3604 if (gl_support_fragment_shader)
3606 qglUseProgramObjectARB(0);CHECKGLERROR
3608 R_MeshQueue_RenderTransparent();
3609 if (r_timereport_active)
3610 R_TimeReport("drawtrans");
3612 if (gl_support_fragment_shader)
3614 qglUseProgramObjectARB(0);CHECKGLERROR
3617 if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3619 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
3620 if (r_timereport_active)
3621 R_TimeReport("worlddebug");
3622 R_DrawModelsDebug();
3623 if (r_timereport_active)
3624 R_TimeReport("modeldebug");
3627 if (gl_support_fragment_shader)
3629 qglUseProgramObjectARB(0);CHECKGLERROR
3632 if (cl.csqc_vidvars.drawworld)
3635 if (r_timereport_active)
3636 R_TimeReport("coronas");
3639 // don't let sound skip if going slow
3640 if (r_refdef.scene.extraupdate)
3643 R_ResetViewRendering2D();
3646 static const int bboxelements[36] =
3656 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3659 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3660 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3661 GL_DepthMask(false);
3662 GL_DepthRange(0, 1);
3663 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3664 R_Mesh_Matrix(&identitymatrix);
3665 R_Mesh_ResetTextureState();
3667 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3668 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3669 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3670 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3671 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3672 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3673 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3674 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3675 R_FillColors(color4f, 8, cr, cg, cb, ca);
3676 if (r_refdef.fogenabled)
3678 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3680 f1 = FogPoint_World(v);
3682 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3683 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3684 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3687 R_Mesh_VertexPointer(vertex3f, 0, 0);
3688 R_Mesh_ColorPointer(color4f, 0, 0);
3689 R_Mesh_ResetTextureState();
3690 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3693 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3697 prvm_edict_t *edict;
3698 // this function draws bounding boxes of server entities
3702 for (i = 0;i < numsurfaces;i++)
3704 edict = PRVM_EDICT_NUM(surfacelist[i]);
3705 switch ((int)edict->fields.server->solid)
3707 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3708 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3709 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3710 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3711 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3712 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3714 color[3] *= r_showbboxes.value;
3715 color[3] = bound(0, color[3], 1);
3716 GL_DepthTest(!r_showdisabledepthtest.integer);
3717 GL_CullFace(r_refdef.view.cullface_front);
3718 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3723 static void R_DrawEntityBBoxes(void)
3726 prvm_edict_t *edict;
3728 // this function draws bounding boxes of server entities
3732 for (i = 0;i < prog->num_edicts;i++)
3734 edict = PRVM_EDICT_NUM(i);
3735 if (edict->priv.server->free)
3737 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3738 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3743 int nomodelelements[24] =
3755 float nomodelvertex3f[6*3] =
3765 float nomodelcolor4f[6*4] =
3767 0.0f, 0.0f, 0.5f, 1.0f,
3768 0.0f, 0.0f, 0.5f, 1.0f,
3769 0.0f, 0.5f, 0.0f, 1.0f,
3770 0.0f, 0.5f, 0.0f, 1.0f,
3771 0.5f, 0.0f, 0.0f, 1.0f,
3772 0.5f, 0.0f, 0.0f, 1.0f
3775 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3780 // this is only called once per entity so numsurfaces is always 1, and
3781 // surfacelist is always {0}, so this code does not handle batches
3782 R_Mesh_Matrix(&ent->matrix);
3784 if (ent->flags & EF_ADDITIVE)
3786 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3787 GL_DepthMask(false);
3789 else if (ent->alpha < 1)
3791 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3792 GL_DepthMask(false);
3796 GL_BlendFunc(GL_ONE, GL_ZERO);
3799 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3800 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3801 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3802 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
3803 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3804 if (r_refdef.fogenabled)
3807 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3808 R_Mesh_ColorPointer(color4f, 0, 0);
3809 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3810 f1 = FogPoint_World(org);
3812 for (i = 0, c = color4f;i < 6;i++, c += 4)
3814 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3815 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3816 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3820 else if (ent->alpha != 1)
3822 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3823 R_Mesh_ColorPointer(color4f, 0, 0);
3824 for (i = 0, c = color4f;i < 6;i++, c += 4)
3828 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3829 R_Mesh_ResetTextureState();
3830 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3833 void R_DrawNoModel(entity_render_t *ent)
3836 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3837 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3838 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3840 // R_DrawNoModelCallback(ent, 0);
3843 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3845 vec3_t right1, right2, diff, normal;
3847 VectorSubtract (org2, org1, normal);
3849 // calculate 'right' vector for start
3850 VectorSubtract (r_refdef.view.origin, org1, diff);
3851 CrossProduct (normal, diff, right1);
3852 VectorNormalize (right1);
3854 // calculate 'right' vector for end
3855 VectorSubtract (r_refdef.view.origin, org2, diff);
3856 CrossProduct (normal, diff, right2);
3857 VectorNormalize (right2);
3859 vert[ 0] = org1[0] + width * right1[0];
3860 vert[ 1] = org1[1] + width * right1[1];
3861 vert[ 2] = org1[2] + width * right1[2];
3862 vert[ 3] = org1[0] - width * right1[0];
3863 vert[ 4] = org1[1] - width * right1[1];
3864 vert[ 5] = org1[2] - width * right1[2];
3865 vert[ 6] = org2[0] - width * right2[0];
3866 vert[ 7] = org2[1] - width * right2[1];
3867 vert[ 8] = org2[2] - width * right2[2];
3868 vert[ 9] = org2[0] + width * right2[0];
3869 vert[10] = org2[1] + width * right2[1];
3870 vert[11] = org2[2] + width * right2[2];
3873 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3875 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, qboolean depthdisable, qboolean depthshort, 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)
3880 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
3881 fog = FogPoint_World(origin);
3883 R_Mesh_Matrix(&identitymatrix);
3884 GL_BlendFunc(blendfunc1, blendfunc2);
3890 GL_CullFace(r_refdef.view.cullface_front);
3893 GL_CullFace(r_refdef.view.cullface_back);
3895 GL_DepthMask(false);
3896 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3897 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3898 GL_DepthTest(!depthdisable);
3900 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3901 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3902 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3903 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3904 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3905 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3906 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3907 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3908 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3909 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3910 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3911 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3913 R_Mesh_VertexPointer(vertex3f, 0, 0);
3914 R_Mesh_ColorPointer(NULL, 0, 0);
3915 R_Mesh_ResetTextureState();
3916 R_Mesh_TexBind(0, R_GetTexture(texture));
3917 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3918 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
3919 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
3920 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3922 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3924 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3925 GL_BlendFunc(blendfunc1, GL_ONE);
3927 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
3928 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3932 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3937 VectorSet(v, x, y, z);
3938 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3939 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3941 if (i == mesh->numvertices)
3943 if (mesh->numvertices < mesh->maxvertices)
3945 VectorCopy(v, vertex3f);
3946 mesh->numvertices++;
3948 return mesh->numvertices;
3954 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3958 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3959 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3960 e = mesh->element3i + mesh->numtriangles * 3;
3961 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3963 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3964 if (mesh->numtriangles < mesh->maxtriangles)
3969 mesh->numtriangles++;
3971 element[1] = element[2];
3975 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3979 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3980 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3981 e = mesh->element3i + mesh->numtriangles * 3;
3982 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3984 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3985 if (mesh->numtriangles < mesh->maxtriangles)
3990 mesh->numtriangles++;
3992 element[1] = element[2];
3996 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3997 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3999 int planenum, planenum2;
4002 mplane_t *plane, *plane2;
4004 double temppoints[2][256*3];
4005 // figure out how large a bounding box we need to properly compute this brush
4007 for (w = 0;w < numplanes;w++)
4008 maxdist = max(maxdist, planes[w].dist);
4009 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4010 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4011 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4015 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4016 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4018 if (planenum2 == planenum)
4020 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);
4023 if (tempnumpoints < 3)
4025 // generate elements forming a triangle fan for this polygon
4026 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4030 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)
4032 texturelayer_t *layer;
4033 layer = t->currentlayers + t->currentnumlayers++;
4035 layer->depthmask = depthmask;
4036 layer->blendfunc1 = blendfunc1;
4037 layer->blendfunc2 = blendfunc2;
4038 layer->texture = texture;
4039 layer->texmatrix = *matrix;
4040 layer->color[0] = r * r_refdef.view.colorscale;
4041 layer->color[1] = g * r_refdef.view.colorscale;
4042 layer->color[2] = b * r_refdef.view.colorscale;
4043 layer->color[3] = a;
4046 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4049 index = parms[2] + r_refdef.scene.time * parms[3];
4050 index -= floor(index);
4054 case Q3WAVEFUNC_NONE:
4055 case Q3WAVEFUNC_NOISE:
4056 case Q3WAVEFUNC_COUNT:
4059 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4060 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4061 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4062 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4063 case Q3WAVEFUNC_TRIANGLE:
4065 f = index - floor(index);
4076 return (float)(parms[0] + parms[1] * f);
4079 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4082 model_t *model = ent->model;
4085 q3shaderinfo_layer_tcmod_t *tcmod;
4087 // switch to an alternate material if this is a q1bsp animated material
4089 texture_t *texture = t;
4090 int s = ent->skinnum;
4091 if ((unsigned int)s >= (unsigned int)model->numskins)
4093 if (model->skinscenes)
4095 if (model->skinscenes[s].framecount > 1)
4096 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4098 s = model->skinscenes[s].firstframe;
4101 t = t + s * model->num_surfaces;
4104 // use an alternate animation if the entity's frame is not 0,
4105 // and only if the texture has an alternate animation
4106 if (ent->frame2 != 0 && t->anim_total[1])
4107 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4109 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4111 texture->currentframe = t;
4114 // update currentskinframe to be a qw skin or animation frame
4115 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4117 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4119 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4120 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4121 r_qwskincache_skinframe[i] = R_SkinFrame_LoadExternal(va("skins/%s", r_qwskincache[i]), TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS, developer.integer > 0);
4123 t->currentskinframe = r_qwskincache_skinframe[i];
4124 if (t->currentskinframe == NULL)
4125 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4127 else if (t->numskinframes >= 2)
4128 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4129 if (t->backgroundnumskinframes >= 2)
4130 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4132 t->currentmaterialflags = t->basematerialflags;
4133 t->currentalpha = ent->alpha;
4134 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4136 t->currentalpha *= r_wateralpha.value;
4138 * FIXME what is this supposed to do?
4139 // if rendering refraction/reflection, disable transparency
4140 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4141 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4144 if(!r_waterstate.enabled)
4145 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4146 if (!(ent->flags & RENDER_LIGHT))
4147 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4148 else if (rsurface.modeltexcoordlightmap2f == NULL)
4150 // pick a model lighting mode
4151 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4152 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4154 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4156 if (ent->effects & EF_ADDITIVE)
4157 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4158 else if (t->currentalpha < 1)
4159 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4160 if (ent->effects & EF_DOUBLESIDED)
4161 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4162 if (ent->effects & EF_NODEPTHTEST)
4163 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4164 if (ent->flags & RENDER_VIEWMODEL)
4165 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4166 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4167 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4168 if (t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST))
4169 t->currentmaterialflags |= MATERIALFLAG_SORTTRANSPARENT;
4170 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATER))
4171 t->currentmaterialflags &= ~MATERIALFLAG_SORTTRANSPARENT;
4173 // make sure that the waterscroll matrix is used on water surfaces when
4174 // there is no tcmod
4175 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4176 t->currenttexmatrix = r_waterscrollmatrix;
4178 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4181 switch(tcmod->tcmod)
4185 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4186 matrix = r_waterscrollmatrix;
4188 matrix = identitymatrix;
4190 case Q3TCMOD_ENTITYTRANSLATE:
4191 // this is used in Q3 to allow the gamecode to control texcoord
4192 // scrolling on the entity, which is not supported in darkplaces yet.
4193 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4195 case Q3TCMOD_ROTATE:
4196 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4197 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4198 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4201 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4203 case Q3TCMOD_SCROLL:
4204 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4206 case Q3TCMOD_STRETCH:
4207 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4208 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4210 case Q3TCMOD_TRANSFORM:
4211 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4212 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4213 VectorSet(tcmat + 6, 0 , 0 , 1);
4214 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4215 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4217 case Q3TCMOD_TURBULENT:
4218 // this is handled in the RSurf_PrepareVertices function
4219 matrix = identitymatrix;
4222 // either replace or concatenate the transformation
4224 t->currenttexmatrix = matrix;
4227 matrix4x4_t temp = t->currenttexmatrix;
4228 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4232 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4233 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4234 t->glosstexture = r_texture_black;
4235 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4236 t->backgroundglosstexture = r_texture_black;
4237 t->specularpower = r_shadow_glossexponent.value;
4238 // TODO: store reference values for these in the texture?
4239 t->specularscale = 0;
4240 if (r_shadow_gloss.integer > 0)
4242 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4244 if (r_shadow_glossintensity.value > 0)
4246 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4247 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4248 t->specularscale = r_shadow_glossintensity.value;
4251 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4253 t->glosstexture = r_texture_white;
4254 t->backgroundglosstexture = r_texture_white;
4255 t->specularscale = r_shadow_gloss2intensity.value;
4259 // lightmaps mode looks bad with dlights using actual texturing, so turn
4260 // off the colormap and glossmap, but leave the normalmap on as it still
4261 // accurately represents the shading involved
4262 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4264 t->basetexture = r_texture_white;
4265 t->specularscale = 0;
4268 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4269 VectorClear(t->dlightcolor);
4270 t->currentnumlayers = 0;
4271 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4273 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4275 int blendfunc1, blendfunc2, depthmask;
4276 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4278 blendfunc1 = GL_SRC_ALPHA;
4279 blendfunc2 = GL_ONE;
4281 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4283 blendfunc1 = GL_SRC_ALPHA;
4284 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4286 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4288 blendfunc1 = t->customblendfunc[0];
4289 blendfunc2 = t->customblendfunc[1];
4293 blendfunc1 = GL_ONE;
4294 blendfunc2 = GL_ZERO;
4296 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4297 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4299 rtexture_t *currentbasetexture;
4301 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4302 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4303 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4304 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4306 // fullbright is not affected by r_refdef.lightmapintensity
4307 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4308 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4309 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4310 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4311 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4315 vec3_t ambientcolor;
4317 // set the color tint used for lights affecting this surface
4318 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4320 // q3bsp has no lightmap updates, so the lightstylevalue that
4321 // would normally be baked into the lightmap must be
4322 // applied to the color
4323 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4324 if (ent->model->type == mod_brushq3)
4325 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4326 colorscale *= r_refdef.lightmapintensity;
4327 VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor);
4328 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4329 // basic lit geometry
4330 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4331 // add pants/shirt if needed
4332 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4333 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4334 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4335 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4336 // now add ambient passes if needed
4337 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4339 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
4340 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4341 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4342 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4343 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4346 if (t->currentskinframe->glow != NULL)
4347 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->lightmapcolor[3]);
4348 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4350 // if this is opaque use alpha blend which will darken the earlier
4353 // if this is an alpha blended material, all the earlier passes
4354 // were darkened by fog already, so we only need to add the fog
4355 // color ontop through the fog mask texture
4357 // if this is an additive blended material, all the earlier passes
4358 // were darkened by fog already, and we should not add fog color
4359 // (because the background was not darkened, there is no fog color
4360 // that was lost behind it).
4361 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.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]);
4368 void R_UpdateAllTextureInfo(entity_render_t *ent)
4372 for (i = 0;i < ent->model->num_texturesperskin;i++)
4373 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4376 rsurfacestate_t rsurface;
4378 void R_Mesh_ResizeArrays(int newvertices)
4381 if (rsurface.array_size >= newvertices)
4383 if (rsurface.array_modelvertex3f)
4384 Mem_Free(rsurface.array_modelvertex3f);
4385 rsurface.array_size = (newvertices + 1023) & ~1023;
4386 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4387 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4388 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4389 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4390 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4391 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4392 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4393 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4394 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4395 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4396 rsurface.array_color4f = base + rsurface.array_size * 27;
4397 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4400 void RSurf_CleanUp(void)
4403 if (rsurface.mode == RSURFMODE_GLSL)
4405 qglUseProgramObjectARB(0);CHECKGLERROR
4407 GL_AlphaTest(false);
4408 rsurface.mode = RSURFMODE_NONE;
4409 rsurface.uselightmaptexture = false;
4410 rsurface.texture = NULL;
4413 void RSurf_ActiveWorldEntity(void)
4415 model_t *model = r_refdef.scene.worldmodel;
4417 if (rsurface.array_size < model->surfmesh.num_vertices)
4418 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4419 rsurface.matrix = identitymatrix;
4420 rsurface.inversematrix = identitymatrix;
4421 R_Mesh_Matrix(&identitymatrix);
4422 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4423 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4424 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4425 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4426 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4427 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4428 rsurface.frameblend[0].frame = 0;
4429 rsurface.frameblend[0].lerp = 1;
4430 rsurface.frameblend[1].frame = 0;
4431 rsurface.frameblend[1].lerp = 0;
4432 rsurface.frameblend[2].frame = 0;
4433 rsurface.frameblend[2].lerp = 0;
4434 rsurface.frameblend[3].frame = 0;
4435 rsurface.frameblend[3].lerp = 0;
4436 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4437 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4438 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4439 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4440 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4441 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4442 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4443 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4444 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4445 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4446 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4447 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4448 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4449 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4450 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4451 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4452 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4453 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4454 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4455 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4456 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4457 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4458 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4459 rsurface.modelelement3i = model->surfmesh.data_element3i;
4460 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4461 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4462 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4463 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4464 rsurface.modelsurfaces = model->data_surfaces;
4465 rsurface.generatedvertex = false;
4466 rsurface.vertex3f = rsurface.modelvertex3f;
4467 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4468 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4469 rsurface.svector3f = rsurface.modelsvector3f;
4470 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4471 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4472 rsurface.tvector3f = rsurface.modeltvector3f;
4473 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4474 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4475 rsurface.normal3f = rsurface.modelnormal3f;
4476 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4477 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4478 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4481 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4483 model_t *model = ent->model;
4485 if (rsurface.array_size < model->surfmesh.num_vertices)
4486 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4487 rsurface.matrix = ent->matrix;
4488 rsurface.inversematrix = ent->inversematrix;
4489 R_Mesh_Matrix(&rsurface.matrix);
4490 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
4491 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4492 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4493 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4494 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4495 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4496 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4497 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4498 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4499 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4500 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4501 rsurface.frameblend[0] = ent->frameblend[0];
4502 rsurface.frameblend[1] = ent->frameblend[1];
4503 rsurface.frameblend[2] = ent->frameblend[2];
4504 rsurface.frameblend[3] = ent->frameblend[3];
4505 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4506 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4507 if (ent->model->brush.submodel)
4509 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4510 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4512 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4516 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4517 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4518 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4519 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4520 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4522 else if (wantnormals)
4524 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4525 rsurface.modelsvector3f = NULL;
4526 rsurface.modeltvector3f = NULL;
4527 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4528 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4532 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4533 rsurface.modelsvector3f = NULL;
4534 rsurface.modeltvector3f = NULL;
4535 rsurface.modelnormal3f = NULL;
4536 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4538 rsurface.modelvertex3f_bufferobject = 0;
4539 rsurface.modelvertex3f_bufferoffset = 0;
4540 rsurface.modelsvector3f_bufferobject = 0;
4541 rsurface.modelsvector3f_bufferoffset = 0;
4542 rsurface.modeltvector3f_bufferobject = 0;
4543 rsurface.modeltvector3f_bufferoffset = 0;
4544 rsurface.modelnormal3f_bufferobject = 0;
4545 rsurface.modelnormal3f_bufferoffset = 0;
4546 rsurface.generatedvertex = true;
4550 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4551 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4552 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4553 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4554 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4555 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4556 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4557 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4558 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4559 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4560 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4561 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4562 rsurface.generatedvertex = false;
4564 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4565 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4566 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4567 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4568 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4569 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4570 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4571 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4572 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4573 rsurface.modelelement3i = model->surfmesh.data_element3i;
4574 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4575 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4576 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4577 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4578 rsurface.modelsurfaces = model->data_surfaces;
4579 rsurface.vertex3f = rsurface.modelvertex3f;
4580 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4581 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4582 rsurface.svector3f = rsurface.modelsvector3f;
4583 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4584 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4585 rsurface.tvector3f = rsurface.modeltvector3f;
4586 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4587 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4588 rsurface.normal3f = rsurface.modelnormal3f;
4589 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4590 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4591 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4594 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4595 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4598 int texturesurfaceindex;
4603 const float *v1, *in_tc;
4605 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4607 q3shaderinfo_deform_t *deform;
4608 // 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
4609 if (rsurface.generatedvertex)
4611 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4612 generatenormals = true;
4613 for (i = 0;i < Q3MAXDEFORMS;i++)
4615 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4617 generatetangents = true;
4618 generatenormals = true;
4620 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4621 generatenormals = true;
4623 if (generatenormals && !rsurface.modelnormal3f)
4625 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4626 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4627 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4628 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4630 if (generatetangents && !rsurface.modelsvector3f)
4632 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4633 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4634 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4635 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4636 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4637 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4638 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer);
4641 rsurface.vertex3f = rsurface.modelvertex3f;
4642 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4643 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4644 rsurface.svector3f = rsurface.modelsvector3f;
4645 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4646 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4647 rsurface.tvector3f = rsurface.modeltvector3f;
4648 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4649 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4650 rsurface.normal3f = rsurface.modelnormal3f;
4651 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4652 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4653 // if vertices are deformed (sprite flares and things in maps, possibly
4654 // water waves, bulges and other deformations), generate them into
4655 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4656 // (may be static model data or generated data for an animated model, or
4657 // the previous deform pass)
4658 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4660 switch (deform->deform)
4663 case Q3DEFORM_PROJECTIONSHADOW:
4664 case Q3DEFORM_TEXT0:
4665 case Q3DEFORM_TEXT1:
4666 case Q3DEFORM_TEXT2:
4667 case Q3DEFORM_TEXT3:
4668 case Q3DEFORM_TEXT4:
4669 case Q3DEFORM_TEXT5:
4670 case Q3DEFORM_TEXT6:
4671 case Q3DEFORM_TEXT7:
4674 case Q3DEFORM_AUTOSPRITE:
4675 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4676 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4677 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4678 VectorNormalize(newforward);
4679 VectorNormalize(newright);
4680 VectorNormalize(newup);
4681 // make deformed versions of only the model vertices used by the specified surfaces
4682 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4684 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4685 // a single autosprite surface can contain multiple sprites...
4686 for (j = 0;j < surface->num_vertices - 3;j += 4)
4688 VectorClear(center);
4689 for (i = 0;i < 4;i++)
4690 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4691 VectorScale(center, 0.25f, center);
4692 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4693 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4694 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4695 for (i = 0;i < 4;i++)
4697 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4698 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4701 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer);
4702 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
4704 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4705 rsurface.vertex3f_bufferobject = 0;
4706 rsurface.vertex3f_bufferoffset = 0;
4707 rsurface.svector3f = rsurface.array_deformedsvector3f;
4708 rsurface.svector3f_bufferobject = 0;
4709 rsurface.svector3f_bufferoffset = 0;
4710 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4711 rsurface.tvector3f_bufferobject = 0;
4712 rsurface.tvector3f_bufferoffset = 0;
4713 rsurface.normal3f = rsurface.array_deformednormal3f;
4714 rsurface.normal3f_bufferobject = 0;
4715 rsurface.normal3f_bufferoffset = 0;
4717 case Q3DEFORM_AUTOSPRITE2:
4718 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4719 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4720 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4721 VectorNormalize(newforward);
4722 VectorNormalize(newright);
4723 VectorNormalize(newup);
4724 // make deformed versions of only the model vertices used by the specified surfaces
4725 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4727 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4728 const float *v1, *v2;
4738 memset(shortest, 0, sizeof(shortest));
4739 // a single autosprite surface can contain multiple sprites...
4740 for (j = 0;j < surface->num_vertices - 3;j += 4)
4742 VectorClear(center);
4743 for (i = 0;i < 4;i++)
4744 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4745 VectorScale(center, 0.25f, center);
4746 // find the two shortest edges, then use them to define the
4747 // axis vectors for rotating around the central axis
4748 for (i = 0;i < 6;i++)
4750 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4751 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4753 Debug_PolygonBegin(NULL, 0, false, 0);
4754 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4755 Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1);
4756 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4759 l = VectorDistance2(v1, v2);
4760 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4762 l += (1.0f / 1024.0f);
4763 if (shortest[0].length2 > l || i == 0)
4765 shortest[1] = shortest[0];
4766 shortest[0].length2 = l;
4767 shortest[0].v1 = v1;
4768 shortest[0].v2 = v2;
4770 else if (shortest[1].length2 > l || i == 1)
4772 shortest[1].length2 = l;
4773 shortest[1].v1 = v1;
4774 shortest[1].v2 = v2;
4777 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4778 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4780 Debug_PolygonBegin(NULL, 0, false, 0);
4781 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4782 Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
4783 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4786 // this calculates the right vector from the shortest edge
4787 // and the up vector from the edge midpoints
4788 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4789 VectorNormalize(right);
4790 VectorSubtract(end, start, up);
4791 VectorNormalize(up);
4792 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4793 //VectorSubtract(rsurface.modelorg, center, forward);
4794 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
4795 VectorNegate(forward, forward);
4796 VectorReflect(forward, 0, up, forward);
4797 VectorNormalize(forward);
4798 CrossProduct(up, forward, newright);
4799 VectorNormalize(newright);
4801 Debug_PolygonBegin(NULL, 0, false, 0);
4802 Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
4803 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4804 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4808 Debug_PolygonBegin(NULL, 0, false, 0);
4809 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4810 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4811 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4814 // rotate the quad around the up axis vector, this is made
4815 // especially easy by the fact we know the quad is flat,
4816 // so we only have to subtract the center position and
4817 // measure distance along the right vector, and then
4818 // multiply that by the newright vector and add back the
4820 // we also need to subtract the old position to undo the
4821 // displacement from the center, which we do with a
4822 // DotProduct, the subtraction/addition of center is also
4823 // optimized into DotProducts here
4824 l = DotProduct(right, center);
4825 for (i = 0;i < 4;i++)
4827 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4828 f = DotProduct(right, v1) - l;
4829 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4832 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer);
4833 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
4835 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4836 rsurface.vertex3f_bufferobject = 0;
4837 rsurface.vertex3f_bufferoffset = 0;
4838 rsurface.svector3f = rsurface.array_deformedsvector3f;
4839 rsurface.svector3f_bufferobject = 0;
4840 rsurface.svector3f_bufferoffset = 0;
4841 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4842 rsurface.tvector3f_bufferobject = 0;
4843 rsurface.tvector3f_bufferoffset = 0;
4844 rsurface.normal3f = rsurface.array_deformednormal3f;
4845 rsurface.normal3f_bufferobject = 0;
4846 rsurface.normal3f_bufferoffset = 0;
4848 case Q3DEFORM_NORMAL:
4849 // deform the normals to make reflections wavey
4850 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4852 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4853 for (j = 0;j < surface->num_vertices;j++)
4856 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4857 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4858 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4859 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
4860 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
4861 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
4862 VectorNormalize(normal);
4864 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
4866 rsurface.svector3f = rsurface.array_deformedsvector3f;
4867 rsurface.svector3f_bufferobject = 0;
4868 rsurface.svector3f_bufferoffset = 0;
4869 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4870 rsurface.tvector3f_bufferobject = 0;
4871 rsurface.tvector3f_bufferoffset = 0;
4872 rsurface.normal3f = rsurface.array_deformednormal3f;
4873 rsurface.normal3f_bufferobject = 0;
4874 rsurface.normal3f_bufferoffset = 0;
4877 // deform vertex array to make wavey water and flags and such
4878 waveparms[0] = deform->waveparms[0];
4879 waveparms[1] = deform->waveparms[1];
4880 waveparms[2] = deform->waveparms[2];
4881 waveparms[3] = deform->waveparms[3];
4882 // this is how a divisor of vertex influence on deformation
4883 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4884 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4885 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4887 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4888 for (j = 0;j < surface->num_vertices;j++)
4890 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4891 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4892 // if the wavefunc depends on time, evaluate it per-vertex
4895 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4896 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4898 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4901 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4902 rsurface.vertex3f_bufferobject = 0;
4903 rsurface.vertex3f_bufferoffset = 0;
4905 case Q3DEFORM_BULGE:
4906 // deform vertex array to make the surface have moving bulges
4907 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4909 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4910 for (j = 0;j < surface->num_vertices;j++)
4912 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
4913 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4916 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4917 rsurface.vertex3f_bufferobject = 0;
4918 rsurface.vertex3f_bufferoffset = 0;
4921 // deform vertex array
4922 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4923 VectorScale(deform->parms, scale, waveparms);
4924 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4926 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4927 for (j = 0;j < surface->num_vertices;j++)
4928 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4930 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4931 rsurface.vertex3f_bufferobject = 0;
4932 rsurface.vertex3f_bufferoffset = 0;
4936 // generate texcoords based on the chosen texcoord source
4937 switch(rsurface.texture->tcgen.tcgen)
4940 case Q3TCGEN_TEXTURE:
4941 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4942 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4943 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4945 case Q3TCGEN_LIGHTMAP:
4946 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4947 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4948 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4950 case Q3TCGEN_VECTOR:
4951 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4953 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4954 for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, out_tc += 2)
4956 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4957 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4960 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4961 rsurface.texcoordtexture2f_bufferobject = 0;
4962 rsurface.texcoordtexture2f_bufferoffset = 0;
4964 case Q3TCGEN_ENVIRONMENT:
4965 // make environment reflections using a spheremap
4966 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4968 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4969 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4970 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4971 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4972 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4974 float l, d, eyedir[3];
4975 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4976 l = 0.5f / VectorLength(eyedir);
4977 d = DotProduct(normal, eyedir)*2;
4978 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4979 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4982 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4983 rsurface.texcoordtexture2f_bufferobject = 0;
4984 rsurface.texcoordtexture2f_bufferoffset = 0;
4987 // the only tcmod that needs software vertex processing is turbulent, so
4988 // check for it here and apply the changes if needed
4989 // and we only support that as the first one
4990 // (handling a mixture of turbulent and other tcmods would be problematic
4991 // without punting it entirely to a software path)
4992 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4994 amplitude = rsurface.texture->tcmods[0].parms[1];
4995 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
4996 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4998 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4999 for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, in_tc = rsurface.texcoordtexture2f + 2 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, in_tc += 2, out_tc += 2)
5001 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5002 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5005 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5006 rsurface.texcoordtexture2f_bufferobject = 0;
5007 rsurface.texcoordtexture2f_bufferoffset = 0;
5009 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5010 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5011 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5012 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5015 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5018 const msurface_t *surface = texturesurfacelist[0];
5019 const msurface_t *surface2;
5024 // TODO: lock all array ranges before render, rather than on each surface
5025 if (texturenumsurfaces == 1)
5027 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5028 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5030 else if (r_batchmode.integer == 2)
5032 #define MAXBATCHTRIANGLES 4096
5033 int batchtriangles = 0;
5034 int batchelements[MAXBATCHTRIANGLES*3];
5035 for (i = 0;i < texturenumsurfaces;i = j)
5037 surface = texturesurfacelist[i];
5039 if (surface->num_triangles > MAXBATCHTRIANGLES)
5041 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5044 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5045 batchtriangles = surface->num_triangles;
5046 firstvertex = surface->num_firstvertex;
5047 endvertex = surface->num_firstvertex + surface->num_vertices;
5048 for (;j < texturenumsurfaces;j++)
5050 surface2 = texturesurfacelist[j];
5051 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5053 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5054 batchtriangles += surface2->num_triangles;
5055 firstvertex = min(firstvertex, surface2->num_firstvertex);
5056 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5058 surface2 = texturesurfacelist[j-1];
5059 numvertices = endvertex - firstvertex;
5060 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5063 else if (r_batchmode.integer == 1)
5065 for (i = 0;i < texturenumsurfaces;i = j)
5067 surface = texturesurfacelist[i];
5068 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5069 if (texturesurfacelist[j] != surface2)
5071 surface2 = texturesurfacelist[j-1];
5072 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5073 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5074 GL_LockArrays(surface->num_firstvertex, numvertices);
5075 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5080 for (i = 0;i < texturenumsurfaces;i++)
5082 surface = texturesurfacelist[i];
5083 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5084 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5089 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5091 int i, planeindex, vertexindex;
5095 r_waterstate_waterplane_t *p, *bestp;
5096 msurface_t *surface;
5097 if (r_waterstate.renderingscene)
5099 for (i = 0;i < texturenumsurfaces;i++)
5101 surface = texturesurfacelist[i];
5102 if (lightmaptexunit >= 0)
5103 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5104 if (deluxemaptexunit >= 0)
5105 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5106 // pick the closest matching water plane
5109 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5112 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5114 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5115 d += fabs(PlaneDiff(vert, &p->plane));
5117 if (bestd > d || !bestp)
5125 if (refractiontexunit >= 0)
5126 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5127 if (reflectiontexunit >= 0)
5128 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5132 if (refractiontexunit >= 0)
5133 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5134 if (reflectiontexunit >= 0)
5135 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5137 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5138 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5142 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5146 const msurface_t *surface = texturesurfacelist[0];
5147 const msurface_t *surface2;
5152 // TODO: lock all array ranges before render, rather than on each surface
5153 if (texturenumsurfaces == 1)
5155 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5156 if (deluxemaptexunit >= 0)
5157 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5158 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5159 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5161 else if (r_batchmode.integer == 2)
5163 #define MAXBATCHTRIANGLES 4096
5164 int batchtriangles = 0;
5165 int batchelements[MAXBATCHTRIANGLES*3];
5166 for (i = 0;i < texturenumsurfaces;i = j)
5168 surface = texturesurfacelist[i];
5169 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5170 if (deluxemaptexunit >= 0)
5171 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5173 if (surface->num_triangles > MAXBATCHTRIANGLES)
5175 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5178 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5179 batchtriangles = surface->num_triangles;
5180 firstvertex = surface->num_firstvertex;
5181 endvertex = surface->num_firstvertex + surface->num_vertices;
5182 for (;j < texturenumsurfaces;j++)
5184 surface2 = texturesurfacelist[j];
5185 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5187 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5188 batchtriangles += surface2->num_triangles;
5189 firstvertex = min(firstvertex, surface2->num_firstvertex);
5190 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5192 surface2 = texturesurfacelist[j-1];
5193 numvertices = endvertex - firstvertex;
5194 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5197 else if (r_batchmode.integer == 1)
5200 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5201 for (i = 0;i < texturenumsurfaces;i = j)
5203 surface = texturesurfacelist[i];
5204 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5205 if (texturesurfacelist[j] != surface2)
5207 Con_Printf(" %i", j - i);
5210 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5212 for (i = 0;i < texturenumsurfaces;i = j)
5214 surface = texturesurfacelist[i];
5215 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5216 if (deluxemaptexunit >= 0)
5217 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5218 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5219 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5222 Con_Printf(" %i", j - i);
5224 surface2 = texturesurfacelist[j-1];
5225 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5226 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5227 GL_LockArrays(surface->num_firstvertex, numvertices);
5228 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5236 for (i = 0;i < texturenumsurfaces;i++)
5238 surface = texturesurfacelist[i];
5239 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5240 if (deluxemaptexunit >= 0)
5241 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5242 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5243 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5248 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5251 int texturesurfaceindex;
5252 if (r_showsurfaces.integer == 2)
5254 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5256 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5257 for (j = 0;j < surface->num_triangles;j++)
5259 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5260 GL_Color(f, f, f, 1);
5261 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface.modelelement3i + 3 * (j + surface->num_firsttriangle)), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * (j + surface->num_firsttriangle)));
5267 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5269 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5270 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5271 GL_Color((k & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1);
5272 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5273 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5278 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5280 int texturesurfaceindex;
5284 if (rsurface.lightmapcolor4f)
5286 // generate color arrays for the surfaces in this list
5287 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5289 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5290 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)
5292 f = FogPoint_Model(v);
5302 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5304 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5305 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)
5307 f = FogPoint_Model(v);
5315 rsurface.lightmapcolor4f = rsurface.array_color4f;
5316 rsurface.lightmapcolor4f_bufferobject = 0;
5317 rsurface.lightmapcolor4f_bufferoffset = 0;
5320 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5322 int texturesurfaceindex;
5325 if (!rsurface.lightmapcolor4f)
5327 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5329 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5330 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)
5338 rsurface.lightmapcolor4f = rsurface.array_color4f;
5339 rsurface.lightmapcolor4f_bufferobject = 0;
5340 rsurface.lightmapcolor4f_bufferoffset = 0;
5343 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5346 rsurface.lightmapcolor4f = NULL;
5347 rsurface.lightmapcolor4f_bufferobject = 0;
5348 rsurface.lightmapcolor4f_bufferoffset = 0;
5349 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5350 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5351 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5352 GL_Color(r, g, b, a);
5353 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5356 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5358 // TODO: optimize applyfog && applycolor case
5359 // just apply fog if necessary, and tint the fog color array if necessary
5360 rsurface.lightmapcolor4f = NULL;
5361 rsurface.lightmapcolor4f_bufferobject = 0;
5362 rsurface.lightmapcolor4f_bufferoffset = 0;
5363 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5364 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5365 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5366 GL_Color(r, g, b, a);
5367 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5370 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5372 int texturesurfaceindex;
5376 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5378 // generate color arrays for the surfaces in this list
5379 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5381 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5382 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5384 if (surface->lightmapinfo->samples)
5386 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5387 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5388 VectorScale(lm, scale, c);
5389 if (surface->lightmapinfo->styles[1] != 255)
5391 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5393 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5394 VectorMA(c, scale, lm, c);
5395 if (surface->lightmapinfo->styles[2] != 255)
5398 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5399 VectorMA(c, scale, lm, c);
5400 if (surface->lightmapinfo->styles[3] != 255)
5403 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5404 VectorMA(c, scale, lm, c);
5414 rsurface.lightmapcolor4f = rsurface.array_color4f;
5415 rsurface.lightmapcolor4f_bufferobject = 0;
5416 rsurface.lightmapcolor4f_bufferoffset = 0;
5420 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5421 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5422 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5424 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5425 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5426 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5427 GL_Color(r, g, b, a);
5428 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5431 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5433 int texturesurfaceindex;
5437 vec3_t ambientcolor;
5438 vec3_t diffusecolor;
5442 VectorCopy(rsurface.modellight_lightdir, lightdir);
5443 f = 0.5f * r_refdef.lightmapintensity;
5444 ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5445 ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5446 ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5447 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5448 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5449 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5450 if (VectorLength2(diffusecolor) > 0)
5452 // generate color arrays for the surfaces in this list
5453 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5455 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5456 int numverts = surface->num_vertices;
5457 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5458 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5459 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5460 // q3-style directional shading
5461 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5463 if ((f = DotProduct(c2, lightdir)) > 0)
5464 VectorMA(ambientcolor, f, diffusecolor, c);
5466 VectorCopy(ambientcolor, c);
5475 rsurface.lightmapcolor4f = rsurface.array_color4f;
5476 rsurface.lightmapcolor4f_bufferobject = 0;
5477 rsurface.lightmapcolor4f_bufferoffset = 0;
5481 r = ambientcolor[0];
5482 g = ambientcolor[1];
5483 b = ambientcolor[2];
5484 rsurface.lightmapcolor4f = NULL;
5485 rsurface.lightmapcolor4f_bufferobject = 0;
5486 rsurface.lightmapcolor4f_bufferoffset = 0;
5488 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5489 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5490 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5491 GL_Color(r, g, b, a);
5492 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5495 void RSurf_SetupDepthAndCulling(void)
5497 // submodels are biased to avoid z-fighting with world surfaces that they
5498 // may be exactly overlapping (avoids z-fighting artifacts on certain
5499 // doors and things in Quake maps)
5500 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5501 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5502 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5503 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
5506 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5508 RSurf_SetupDepthAndCulling();
5509 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5511 rsurface.mode = RSURFMODE_SHOWSURFACES;
5513 GL_BlendFunc(GL_ONE, GL_ZERO);
5514 R_Mesh_ColorPointer(NULL, 0, 0);
5515 R_Mesh_ResetTextureState();
5517 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5518 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5521 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5523 // transparent sky would be ridiculous
5524 if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SORTTRANSPARENT))
5526 if (rsurface.mode != RSURFMODE_SKY)
5528 if (rsurface.mode == RSURFMODE_GLSL)
5530 qglUseProgramObjectARB(0);CHECKGLERROR
5532 rsurface.mode = RSURFMODE_SKY;
5536 skyrendernow = false;
5538 // restore entity matrix
5539 R_Mesh_Matrix(&rsurface.matrix);
5541 RSurf_SetupDepthAndCulling();
5543 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5544 // skymasking on them, and Quake3 never did sky masking (unlike
5545 // software Quake and software Quake2), so disable the sky masking
5546 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5547 // and skymasking also looks very bad when noclipping outside the
5548 // level, so don't use it then either.
5549 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
5551 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5552 R_Mesh_ColorPointer(NULL, 0, 0);
5553 R_Mesh_ResetTextureState();
5554 if (skyrendermasked)
5556 // depth-only (masking)
5557 GL_ColorMask(0,0,0,0);
5558 // just to make sure that braindead drivers don't draw
5559 // anything despite that colormask...
5560 GL_BlendFunc(GL_ZERO, GL_ONE);
5565 GL_BlendFunc(GL_ONE, GL_ZERO);
5567 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5568 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5569 if (skyrendermasked)
5570 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5574 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5576 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5579 if (rsurface.mode != RSURFMODE_GLSL)
5581 rsurface.mode = RSURFMODE_GLSL;
5582 R_Mesh_ResetTextureState();
5583 GL_Color(1, 1, 1, 1);
5586 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5587 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5588 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5589 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5590 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5591 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5592 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5593 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5595 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5596 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5597 R_Mesh_ColorPointer(NULL, 0, 0);
5599 else if (rsurface.uselightmaptexture)
5601 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5602 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5603 R_Mesh_ColorPointer(NULL, 0, 0);
5607 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5608 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5609 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5611 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5612 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5613 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5615 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5617 // render background
5618 GL_BlendFunc(GL_ONE, GL_ZERO);
5620 GL_AlphaTest(false);
5622 GL_Color(1, 1, 1, 1);
5623 R_Mesh_ColorPointer(NULL, 0, 0);
5625 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5626 if (r_glsl_permutation)
5628 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5629 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5630 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5631 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5632 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5633 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5634 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5637 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5638 GL_DepthMask(false);
5639 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5640 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5642 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5643 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5644 R_Mesh_ColorPointer(NULL, 0, 0);
5646 else if (rsurface.uselightmaptexture)
5648 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5649 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5650 R_Mesh_ColorPointer(NULL, 0, 0);
5654 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5655 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5656 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5658 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5659 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5662 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5663 if (!r_glsl_permutation)
5666 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5667 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5668 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5669 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5670 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5671 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5673 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5675 GL_BlendFunc(GL_ONE, GL_ZERO);
5677 GL_AlphaTest(false);
5680 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5682 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5683 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? 12 : -1);
5685 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5689 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5690 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? 12 : -1);
5692 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5696 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5698 // OpenGL 1.3 path - anything not completely ancient
5699 int texturesurfaceindex;
5700 qboolean applycolor;
5704 const texturelayer_t *layer;
5705 if (rsurface.mode != RSURFMODE_MULTIPASS)
5706 rsurface.mode = RSURFMODE_MULTIPASS;
5707 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5709 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5712 int layertexrgbscale;
5713 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5715 if (layerindex == 0)
5719 GL_AlphaTest(false);
5720 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5723 GL_DepthMask(layer->depthmask);
5724 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5725 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
5727 layertexrgbscale = 4;
5728 VectorScale(layer->color, 0.25f, layercolor);
5730 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
5732 layertexrgbscale = 2;
5733 VectorScale(layer->color, 0.5f, layercolor);
5737 layertexrgbscale = 1;
5738 VectorScale(layer->color, 1.0f, layercolor);
5740 layercolor[3] = layer->color[3];
5741 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5742 R_Mesh_ColorPointer(NULL, 0, 0);
5743 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5744 switch (layer->type)
5746 case TEXTURELAYERTYPE_LITTEXTURE:
5747 memset(&m, 0, sizeof(m));
5748 m.tex[0] = R_GetTexture(r_texture_white);
5749 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5750 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5751 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5752 m.tex[1] = R_GetTexture(layer->texture);
5753 m.texmatrix[1] = layer->texmatrix;
5754 m.texrgbscale[1] = layertexrgbscale;
5755 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5756 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5757 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5758 R_Mesh_TextureState(&m);
5759 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5760 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5761 else if (rsurface.uselightmaptexture)
5762 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5764 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5766 case TEXTURELAYERTYPE_TEXTURE:
5767 memset(&m, 0, sizeof(m));
5768 m.tex[0] = R_GetTexture(layer->texture);
5769 m.texmatrix[0] = layer->texmatrix;
5770 m.texrgbscale[0] = layertexrgbscale;
5771 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5772 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5773 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5774 R_Mesh_TextureState(&m);
5775 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5777 case TEXTURELAYERTYPE_FOG:
5778 memset(&m, 0, sizeof(m));
5779 m.texrgbscale[0] = layertexrgbscale;
5782 m.tex[0] = R_GetTexture(layer->texture);
5783 m.texmatrix[0] = layer->texmatrix;
5784 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5785 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5786 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5788 R_Mesh_TextureState(&m);
5789 // generate a color array for the fog pass
5790 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5791 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5795 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5796 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)
5798 f = 1 - FogPoint_Model(v);
5799 c[0] = layercolor[0];
5800 c[1] = layercolor[1];
5801 c[2] = layercolor[2];
5802 c[3] = f * layercolor[3];
5805 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5808 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5810 GL_LockArrays(0, 0);
5813 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5815 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5816 GL_AlphaTest(false);
5820 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5822 // OpenGL 1.1 - crusty old voodoo path
5823 int texturesurfaceindex;
5827 const texturelayer_t *layer;
5828 if (rsurface.mode != RSURFMODE_MULTIPASS)
5829 rsurface.mode = RSURFMODE_MULTIPASS;
5830 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5832 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5834 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5836 if (layerindex == 0)
5840 GL_AlphaTest(false);
5841 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5844 GL_DepthMask(layer->depthmask);
5845 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5846 R_Mesh_ColorPointer(NULL, 0, 0);
5847 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5848 switch (layer->type)
5850 case TEXTURELAYERTYPE_LITTEXTURE:
5851 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5853 // two-pass lit texture with 2x rgbscale
5854 // first the lightmap pass
5855 memset(&m, 0, sizeof(m));
5856 m.tex[0] = R_GetTexture(r_texture_white);
5857 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5858 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5859 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5860 R_Mesh_TextureState(&m);
5861 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5862 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5863 else if (rsurface.uselightmaptexture)
5864 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5866 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5867 GL_LockArrays(0, 0);
5868 // then apply the texture to it
5869 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5870 memset(&m, 0, sizeof(m));
5871 m.tex[0] = R_GetTexture(layer->texture);
5872 m.texmatrix[0] = layer->texmatrix;
5873 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5874 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5875 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5876 R_Mesh_TextureState(&m);
5877 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
5881 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5882 memset(&m, 0, sizeof(m));
5883 m.tex[0] = R_GetTexture(layer->texture);
5884 m.texmatrix[0] = layer->texmatrix;
5885 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5886 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5887 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5888 R_Mesh_TextureState(&m);
5889 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5890 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
5892 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
5895 case TEXTURELAYERTYPE_TEXTURE:
5896 // singletexture unlit texture with transparency support
5897 memset(&m, 0, sizeof(m));
5898 m.tex[0] = R_GetTexture(layer->texture);
5899 m.texmatrix[0] = layer->texmatrix;
5900 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5901 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5902 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5903 R_Mesh_TextureState(&m);
5904 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
5906 case TEXTURELAYERTYPE_FOG:
5907 // singletexture fogging
5908 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5911 memset(&m, 0, sizeof(m));
5912 m.tex[0] = R_GetTexture(layer->texture);
5913 m.texmatrix[0] = layer->texmatrix;
5914 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5915 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5916 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5917 R_Mesh_TextureState(&m);
5920 R_Mesh_ResetTextureState();
5921 // generate a color array for the fog pass
5922 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5926 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5927 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)
5929 f = 1 - FogPoint_Model(v);
5930 c[0] = layer->color[0];
5931 c[1] = layer->color[1];
5932 c[2] = layer->color[2];
5933 c[3] = f * layer->color[3];
5936 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5939 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5941 GL_LockArrays(0, 0);
5944 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5946 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5947 GL_AlphaTest(false);
5951 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5953 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5955 rsurface.rtlight = NULL;
5959 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5961 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5963 if (rsurface.mode != RSURFMODE_MULTIPASS)
5964 rsurface.mode = RSURFMODE_MULTIPASS;
5965 if (r_depthfirst.integer == 3)
5967 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5968 if (!r_refdef.view.showdebug)
5969 GL_Color(0, 0, 0, 1);
5971 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5975 GL_ColorMask(0,0,0,0);
5978 RSurf_SetupDepthAndCulling();
5980 GL_BlendFunc(GL_ONE, GL_ZERO);
5982 GL_AlphaTest(false);
5983 R_Mesh_ColorPointer(NULL, 0, 0);
5984 R_Mesh_ResetTextureState();
5985 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5986 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5987 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5989 else if (r_depthfirst.integer == 3)
5991 else if (!r_refdef.view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5993 GL_Color(0, 0, 0, 1);
5994 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5996 else if (r_showsurfaces.integer)
5998 if (rsurface.mode != RSURFMODE_MULTIPASS)
5999 rsurface.mode = RSURFMODE_MULTIPASS;
6000 RSurf_SetupDepthAndCulling();
6002 GL_BlendFunc(GL_ONE, GL_ZERO);
6003 GL_DepthMask(writedepth);
6005 GL_AlphaTest(false);
6006 R_Mesh_ColorPointer(NULL, 0, 0);
6007 R_Mesh_ResetTextureState();
6008 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6009 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6011 else if (gl_lightmaps.integer)
6014 if (rsurface.mode != RSURFMODE_MULTIPASS)
6015 rsurface.mode = RSURFMODE_MULTIPASS;
6016 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6018 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6019 GL_BlendFunc(GL_ONE, GL_ZERO);
6020 GL_DepthMask(writedepth);
6022 GL_AlphaTest(false);
6023 R_Mesh_ColorPointer(NULL, 0, 0);
6024 memset(&m, 0, sizeof(m));
6025 m.tex[0] = R_GetTexture(r_texture_white);
6026 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6027 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6028 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6029 R_Mesh_TextureState(&m);
6030 RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist);
6031 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6032 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6033 else if (rsurface.uselightmaptexture)
6034 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6036 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6038 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6039 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6040 else if (rsurface.texture->currentnumlayers)
6042 // write depth for anything we skipped on the depth-only pass earlier
6043 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6045 RSurf_SetupDepthAndCulling();
6046 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6047 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6048 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6049 if (r_glsl.integer && gl_support_fragment_shader)
6050 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
6051 else if (gl_combine.integer && r_textureunits.integer >= 2)
6052 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
6054 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
6057 GL_LockArrays(0, 0);
6060 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6063 int texturenumsurfaces, endsurface;
6065 msurface_t *surface;
6066 msurface_t *texturesurfacelist[1024];
6068 // if the model is static it doesn't matter what value we give for
6069 // wantnormals and wanttangents, so this logic uses only rules applicable
6070 // to a model, knowing that they are meaningless otherwise
6071 if (ent == r_refdef.scene.worldentity)
6072 RSurf_ActiveWorldEntity();
6073 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6074 RSurf_ActiveModelEntity(ent, false, false);
6076 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6078 for (i = 0;i < numsurfaces;i = j)
6081 surface = rsurface.modelsurfaces + surfacelist[i];
6082 texture = surface->texture;
6083 R_UpdateTextureInfo(ent, texture);
6084 rsurface.texture = texture->currentframe;
6085 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6086 // scan ahead until we find a different texture
6087 endsurface = min(i + 1024, numsurfaces);
6088 texturenumsurfaces = 0;
6089 texturesurfacelist[texturenumsurfaces++] = surface;
6090 for (;j < endsurface;j++)
6092 surface = rsurface.modelsurfaces + surfacelist[j];
6093 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6095 texturesurfacelist[texturenumsurfaces++] = surface;
6097 // render the range of surfaces
6098 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
6104 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6107 vec3_t tempcenter, center;
6109 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6112 for (i = 0;i < numsurfaces;i++)
6113 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6114 R_Water_AddWaterPlane(surfacelist[i]);
6117 // break the surface list down into batches by texture and use of lightmapping
6118 for (i = 0;i < numsurfaces;i = j)
6121 // texture is the base texture pointer, rsurface.texture is the
6122 // current frame/skin the texture is directing us to use (for example
6123 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6124 // use skin 1 instead)
6125 texture = surfacelist[i]->texture;
6126 rsurface.texture = texture->currentframe;
6127 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6128 if (!(rsurface.texture->currentmaterialflags & flagsmask))
6130 // if this texture is not the kind we want, skip ahead to the next one
6131 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6135 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SORTTRANSPARENT)
6137 // transparent surfaces get pushed off into the transparent queue
6138 const msurface_t *surface = surfacelist[i];
6141 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6142 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6143 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6144 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6145 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
6149 // simply scan ahead until we find a different texture or lightmap state
6150 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6152 // render the range of surfaces
6153 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6158 float locboxvertex3f[6*4*3] =
6160 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6161 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6162 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6163 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6164 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6165 1,0,0, 0,0,0, 0,1,0, 1,1,0
6168 int locboxelement3i[6*2*3] =
6178 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6181 cl_locnode_t *loc = (cl_locnode_t *)ent;
6183 float vertex3f[6*4*3];
6185 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6186 GL_DepthMask(false);
6187 GL_DepthRange(0, 1);
6188 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6190 GL_CullFace(GL_NONE);
6191 R_Mesh_Matrix(&identitymatrix);
6193 R_Mesh_VertexPointer(vertex3f, 0, 0);
6194 R_Mesh_ColorPointer(NULL, 0, 0);
6195 R_Mesh_ResetTextureState();
6198 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6199 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6200 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6201 surfacelist[0] < 0 ? 0.5f : 0.125f);
6203 if (VectorCompare(loc->mins, loc->maxs))
6205 VectorSet(size, 2, 2, 2);
6206 VectorMA(loc->mins, -0.5f, size, mins);
6210 VectorCopy(loc->mins, mins);
6211 VectorSubtract(loc->maxs, loc->mins, size);
6214 for (i = 0;i < 6*4*3;)
6215 for (j = 0;j < 3;j++, i++)
6216 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6218 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6221 void R_DrawLocs(void)
6224 cl_locnode_t *loc, *nearestloc;
6226 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6227 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6229 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6230 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6234 void R_DrawDebugModel(entity_render_t *ent)
6236 int i, j, k, l, flagsmask;
6237 const int *elements;
6239 msurface_t *surface;
6240 model_t *model = ent->model;
6243 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6245 R_Mesh_ColorPointer(NULL, 0, 0);
6246 R_Mesh_ResetTextureState();
6247 GL_DepthRange(0, 1);
6248 GL_DepthTest(!r_showdisabledepthtest.integer);
6249 GL_DepthMask(false);
6250 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6252 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6254 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6255 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6257 if (brush->colbrushf && brush->colbrushf->numtriangles)
6259 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6260 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
6261 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6264 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6266 if (surface->num_collisiontriangles)
6268 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6269 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
6270 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6275 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6277 if (r_showtris.integer || r_shownormals.integer)
6279 if (r_showdisabledepthtest.integer)
6281 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6282 GL_DepthMask(false);
6286 GL_BlendFunc(GL_ONE, GL_ZERO);
6289 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6291 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
6293 rsurface.texture = surface->texture->currentframe;
6294 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6296 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6297 if (r_showtris.value > 0)
6299 if (!rsurface.texture->currentlayers->depthmask)
6300 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
6301 else if (ent == r_refdef.scene.worldentity)
6302 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
6304 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
6305 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6308 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6310 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6311 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6312 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6313 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6318 if (r_shownormals.value > 0)
6321 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6323 VectorCopy(rsurface.vertex3f + l * 3, v);
6324 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
6325 qglVertex3f(v[0], v[1], v[2]);
6326 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6327 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6328 qglVertex3f(v[0], v[1], v[2]);
6333 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6335 VectorCopy(rsurface.vertex3f + l * 3, v);
6336 GL_Color(0, r_refdef.view.colorscale, 0, 1);
6337 qglVertex3f(v[0], v[1], v[2]);
6338 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6339 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6340 qglVertex3f(v[0], v[1], v[2]);
6345 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6347 VectorCopy(rsurface.vertex3f + l * 3, v);
6348 GL_Color(0, 0, r_refdef.view.colorscale, 1);
6349 qglVertex3f(v[0], v[1], v[2]);
6350 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6351 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6352 qglVertex3f(v[0], v[1], v[2]);
6359 rsurface.texture = NULL;
6363 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6364 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6366 int i, j, endj, f, flagsmask;
6367 msurface_t *surface;
6369 model_t *model = r_refdef.scene.worldmodel;
6370 const int maxsurfacelist = 1024;
6371 int numsurfacelist = 0;
6372 msurface_t *surfacelist[1024];
6376 RSurf_ActiveWorldEntity();
6378 // update light styles on this submodel
6379 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6381 model_brush_lightstyleinfo_t *style;
6382 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6384 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6386 msurface_t *surfaces = model->data_surfaces;
6387 int *list = style->surfacelist;
6388 style->value = r_refdef.scene.lightstylevalue[style->style];
6389 for (j = 0;j < style->numsurfaces;j++)
6390 surfaces[list[j]].cached_dlight = true;
6395 R_UpdateAllTextureInfo(r_refdef.scene.worldentity);
6396 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6400 R_DrawDebugModel(r_refdef.scene.worldentity);
6406 rsurface.uselightmaptexture = false;
6407 rsurface.texture = NULL;
6409 j = model->firstmodelsurface;
6410 endj = j + model->nummodelsurfaces;
6413 // quickly skip over non-visible surfaces
6414 for (;j < endj && !r_refdef.viewcache.world_surfacevisible[j];j++)
6416 // quickly iterate over visible surfaces
6417 for (;j < endj && r_refdef.viewcache.world_surfacevisible[j];j++)
6419 // process this surface
6420 surface = model->data_surfaces + j;
6421 // if this surface fits the criteria, add it to the list
6422 if (surface->num_triangles)
6424 // if lightmap parameters changed, rebuild lightmap texture
6425 if (surface->cached_dlight)
6426 R_BuildLightMap(r_refdef.scene.worldentity, surface);
6427 // add face to draw list
6428 surfacelist[numsurfacelist++] = surface;
6429 r_refdef.stats.world_triangles += surface->num_triangles;
6430 if (numsurfacelist >= maxsurfacelist)
6432 r_refdef.stats.world_surfaces += numsurfacelist;
6433 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6439 r_refdef.stats.world_surfaces += numsurfacelist;
6441 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6445 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6447 int i, j, f, flagsmask;
6448 msurface_t *surface, *endsurface;
6450 model_t *model = ent->model;
6451 const int maxsurfacelist = 1024;
6452 int numsurfacelist = 0;
6453 msurface_t *surfacelist[1024];
6457 // if the model is static it doesn't matter what value we give for
6458 // wantnormals and wanttangents, so this logic uses only rules applicable
6459 // to a model, knowing that they are meaningless otherwise
6460 if (ent == r_refdef.scene.worldentity)
6461 RSurf_ActiveWorldEntity();
6462 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6463 RSurf_ActiveModelEntity(ent, false, false);
6465 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6467 // update light styles
6468 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6470 model_brush_lightstyleinfo_t *style;
6471 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6473 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6475 msurface_t *surfaces = model->data_surfaces;
6476 int *list = style->surfacelist;
6477 style->value = r_refdef.scene.lightstylevalue[style->style];
6478 for (j = 0;j < style->numsurfaces;j++)
6479 surfaces[list[j]].cached_dlight = true;
6484 R_UpdateAllTextureInfo(ent);
6485 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6489 R_DrawDebugModel(ent);
6495 rsurface.uselightmaptexture = false;
6496 rsurface.texture = NULL;
6498 surface = model->data_surfaces + model->firstmodelsurface;
6499 endsurface = surface + model->nummodelsurfaces;
6500 for (;surface < endsurface;surface++)
6502 // if this surface fits the criteria, add it to the list
6503 if (surface->num_triangles)
6505 // if lightmap parameters changed, rebuild lightmap texture
6506 if (surface->cached_dlight)
6507 R_BuildLightMap(ent, surface);
6508 // add face to draw list
6509 surfacelist[numsurfacelist++] = surface;
6510 r_refdef.stats.entities_triangles += surface->num_triangles;
6511 if (numsurfacelist >= maxsurfacelist)
6513 r_refdef.stats.entities_surfaces += numsurfacelist;
6514 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6519 r_refdef.stats.entities_surfaces += numsurfacelist;
6521 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);