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 if (specularscale > 0)
1383 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1385 else if (r_glsl_deluxemapping.integer >= 2)
1387 // fake deluxemapping (uniform light direction in tangentspace)
1388 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1389 if (specularscale > 0)
1390 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1392 else if (rsurface.uselightmaptexture)
1394 // ordinary lightmapping (q1bsp, q3bsp)
1395 mode = SHADERMODE_LIGHTMAP;
1399 // ordinary vertex coloring (q3bsp)
1400 mode = SHADERMODE_VERTEXCOLOR;
1402 if (rsurface.texture->currentskinframe->glow)
1403 permutation |= SHADERPERMUTATION_GLOW;
1404 if (r_refdef.fogenabled)
1405 permutation |= SHADERPERMUTATION_FOG;
1406 if (rsurface.texture->colormapping)
1407 permutation |= SHADERPERMUTATION_COLORMAPPING;
1408 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1409 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1410 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1411 permutation |= SHADERPERMUTATION_REFLECTION;
1413 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1414 if (!r_glsl_permutation->program)
1416 if (!r_glsl_permutation->compiled)
1417 R_GLSL_CompilePermutation(mode, permutation);
1418 if (!r_glsl_permutation->program)
1420 // remove features until we find a valid permutation
1422 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1424 // reduce i more quickly whenever it would not remove any bits
1425 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1426 if (!(permutation & j))
1429 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1430 if (!r_glsl_permutation->compiled)
1431 R_GLSL_CompilePermutation(mode, permutation);
1432 if (r_glsl_permutation->program)
1435 if (i >= SHADERPERMUTATION_COUNT)
1437 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");
1438 Cvar_SetValueQuick(&r_glsl, 0);
1439 return 0; // no bit left to clear
1444 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1445 if (mode == SHADERMODE_LIGHTSOURCE)
1447 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1448 if (permutation & SHADERPERMUTATION_DIFFUSE)
1450 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1451 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1452 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1453 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1457 // ambient only is simpler
1458 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1459 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1460 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1461 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1464 else if (mode == SHADERMODE_LIGHTDIRECTION)
1466 if (r_glsl_permutation->loc_AmbientColor >= 0)
1467 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);
1468 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1469 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);
1470 if (r_glsl_permutation->loc_SpecularColor >= 0)
1471 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);
1472 if (r_glsl_permutation->loc_LightDir >= 0)
1473 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1477 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
1478 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1479 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1481 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]);
1482 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1483 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1485 // The formula used is actually:
1486 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1487 // color.rgb *= SceneBrightness;
1489 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1490 // and do [[calculations]] here in the engine
1491 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1492 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1495 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1496 if (r_glsl_permutation->loc_FogColor >= 0)
1498 // additive passes are only darkened by fog, not tinted
1499 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1500 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1502 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1504 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1505 if (r_glsl_permutation->loc_Color_Pants >= 0)
1507 if (rsurface.texture->currentskinframe->pants)
1508 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1510 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1512 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1514 if (rsurface.texture->currentskinframe->shirt)
1515 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1517 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1519 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1520 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1521 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1522 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);
1523 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]);
1524 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]);
1525 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1526 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1527 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1528 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1533 #define SKINFRAME_HASH 1024
1537 int loadsequence; // incremented each level change
1538 memexpandablearray_t array;
1539 skinframe_t *hash[SKINFRAME_HASH];
1543 void R_SkinFrame_PrepareForPurge(void)
1545 r_skinframe.loadsequence++;
1546 // wrap it without hitting zero
1547 if (r_skinframe.loadsequence >= 200)
1548 r_skinframe.loadsequence = 1;
1551 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1555 // mark the skinframe as used for the purging code
1556 skinframe->loadsequence = r_skinframe.loadsequence;
1559 void R_SkinFrame_Purge(void)
1563 for (i = 0;i < SKINFRAME_HASH;i++)
1565 for (s = r_skinframe.hash[i];s;s = s->next)
1567 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1569 if (s->merged == s->base)
1571 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1572 R_PurgeTexture(s->stain );s->stain = NULL;
1573 R_PurgeTexture(s->merged);s->merged = NULL;
1574 R_PurgeTexture(s->base );s->base = NULL;
1575 R_PurgeTexture(s->pants );s->pants = NULL;
1576 R_PurgeTexture(s->shirt );s->shirt = NULL;
1577 R_PurgeTexture(s->nmap );s->nmap = NULL;
1578 R_PurgeTexture(s->gloss );s->gloss = NULL;
1579 R_PurgeTexture(s->glow );s->glow = NULL;
1580 R_PurgeTexture(s->fog );s->fog = NULL;
1581 s->loadsequence = 0;
1587 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1589 char basename[MAX_QPATH];
1591 Image_StripImageExtension(name, basename, sizeof(basename));
1593 if( last == NULL ) {
1595 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1596 item = r_skinframe.hash[hashindex];
1601 // linearly search through the hash bucket
1602 for( ; item ; item = item->next ) {
1603 if( !strcmp( item->basename, basename ) ) {
1610 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1614 char basename[MAX_QPATH];
1616 Image_StripImageExtension(name, basename, sizeof(basename));
1618 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1619 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1620 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1624 rtexture_t *dyntexture;
1625 // check whether its a dynamic texture
1626 dyntexture = CL_GetDynTexture( basename );
1627 if (!add && !dyntexture)
1629 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1630 memset(item, 0, sizeof(*item));
1631 strlcpy(item->basename, basename, sizeof(item->basename));
1632 item->base = dyntexture; // either NULL or dyntexture handle
1633 item->textureflags = textureflags;
1634 item->comparewidth = comparewidth;
1635 item->compareheight = compareheight;
1636 item->comparecrc = comparecrc;
1637 item->next = r_skinframe.hash[hashindex];
1638 r_skinframe.hash[hashindex] = item;
1640 else if( item->base == NULL )
1642 rtexture_t *dyntexture;
1643 // check whether its a dynamic texture
1644 // 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]
1645 dyntexture = CL_GetDynTexture( basename );
1646 item->base = dyntexture; // either NULL or dyntexture handle
1649 R_SkinFrame_MarkUsed(item);
1653 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1655 // FIXME: it should be possible to disable loading various layers using
1656 // cvars, to prevent wasted loading time and memory usage if the user does
1658 qboolean loadnormalmap = true;
1659 qboolean loadgloss = true;
1660 qboolean loadpantsandshirt = true;
1661 qboolean loadglow = true;
1663 unsigned char *pixels;
1664 unsigned char *bumppixels;
1665 unsigned char *basepixels = NULL;
1666 int basepixels_width;
1667 int basepixels_height;
1668 skinframe_t *skinframe;
1670 if (cls.state == ca_dedicated)
1673 // return an existing skinframe if already loaded
1674 // if loading of the first image fails, don't make a new skinframe as it
1675 // would cause all future lookups of this to be missing
1676 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1677 if (skinframe && skinframe->base)
1680 basepixels = loadimagepixelsbgra(name, complain, true);
1681 if (basepixels == NULL)
1684 // we've got some pixels to store, so really allocate this new texture now
1686 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1687 skinframe->stain = NULL;
1688 skinframe->merged = NULL;
1689 skinframe->base = r_texture_notexture;
1690 skinframe->pants = NULL;
1691 skinframe->shirt = NULL;
1692 skinframe->nmap = r_texture_blanknormalmap;
1693 skinframe->gloss = NULL;
1694 skinframe->glow = NULL;
1695 skinframe->fog = NULL;
1697 basepixels_width = image_width;
1698 basepixels_height = image_height;
1699 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);
1701 if (textureflags & TEXF_ALPHA)
1703 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1704 if (basepixels[j] < 255)
1706 if (j < basepixels_width * basepixels_height * 4)
1708 // has transparent pixels
1709 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1710 for (j = 0;j < image_width * image_height * 4;j += 4)
1715 pixels[j+3] = basepixels[j+3];
1717 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);
1722 // _norm is the name used by tenebrae and has been adopted as standard
1725 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1727 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);
1731 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1733 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1734 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1735 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);
1737 Mem_Free(bumppixels);
1739 else if (r_shadow_bumpscale_basetexture.value > 0)
1741 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1742 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1743 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);
1747 // _luma is supported for tenebrae compatibility
1748 // (I think it's a very stupid name, but oh well)
1749 // _glow is the preferred name
1750 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;}
1751 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;}
1752 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;}
1753 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;}
1756 Mem_Free(basepixels);
1761 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)
1766 for (i = 0;i < width*height;i++)
1767 if (((unsigned char *)&palette[in[i]])[3] > 0)
1769 if (i == width*height)
1772 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1775 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
1776 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
1779 unsigned char *temp1, *temp2;
1780 skinframe_t *skinframe;
1782 if (cls.state == ca_dedicated)
1785 // if already loaded just return it, otherwise make a new skinframe
1786 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
1787 if (skinframe && skinframe->base)
1790 skinframe->stain = NULL;
1791 skinframe->merged = NULL;
1792 skinframe->base = r_texture_notexture;
1793 skinframe->pants = NULL;
1794 skinframe->shirt = NULL;
1795 skinframe->nmap = r_texture_blanknormalmap;
1796 skinframe->gloss = NULL;
1797 skinframe->glow = NULL;
1798 skinframe->fog = NULL;
1800 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1804 if (r_shadow_bumpscale_basetexture.value > 0)
1806 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1807 temp2 = temp1 + width * height * 4;
1808 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1809 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1812 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1813 if (textureflags & TEXF_ALPHA)
1815 for (i = 3;i < width * height * 4;i += 4)
1816 if (skindata[i] < 255)
1818 if (i < width * height * 4)
1820 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1821 memcpy(fogpixels, skindata, width * height * 4);
1822 for (i = 0;i < width * height * 4;i += 4)
1823 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1824 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1825 Mem_Free(fogpixels);
1832 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
1835 unsigned char *temp1, *temp2;
1836 skinframe_t *skinframe;
1838 if (cls.state == ca_dedicated)
1841 // if already loaded just return it, otherwise make a new skinframe
1842 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
1843 if (skinframe && skinframe->base)
1846 skinframe->stain = NULL;
1847 skinframe->merged = NULL;
1848 skinframe->base = r_texture_notexture;
1849 skinframe->pants = NULL;
1850 skinframe->shirt = NULL;
1851 skinframe->nmap = r_texture_blanknormalmap;
1852 skinframe->gloss = NULL;
1853 skinframe->glow = NULL;
1854 skinframe->fog = NULL;
1856 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1860 if (r_shadow_bumpscale_basetexture.value > 0)
1862 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1863 temp2 = temp1 + width * height * 4;
1864 // use either a custom palette or the quake palette
1865 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
1866 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1867 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1870 // use either a custom palette, or the quake palette
1871 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
1872 if (loadglowtexture)
1873 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
1874 if (loadpantsandshirt)
1876 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
1877 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
1879 if (skinframe->pants || skinframe->shirt)
1880 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
1881 if (textureflags & TEXF_ALPHA)
1883 for (i = 0;i < width * height;i++)
1884 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
1886 if (i < width * height)
1887 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
1893 skinframe_t *R_SkinFrame_LoadMissing(void)
1895 skinframe_t *skinframe;
1897 if (cls.state == ca_dedicated)
1900 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1901 skinframe->stain = NULL;
1902 skinframe->merged = NULL;
1903 skinframe->base = r_texture_notexture;
1904 skinframe->pants = NULL;
1905 skinframe->shirt = NULL;
1906 skinframe->nmap = r_texture_blanknormalmap;
1907 skinframe->gloss = NULL;
1908 skinframe->glow = NULL;
1909 skinframe->fog = NULL;
1914 void gl_main_start(void)
1916 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1917 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1919 // set up r_skinframe loading system for textures
1920 memset(&r_skinframe, 0, sizeof(r_skinframe));
1921 r_skinframe.loadsequence = 1;
1922 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1924 r_main_texturepool = R_AllocTexturePool();
1925 R_BuildBlankTextures();
1927 if (gl_texturecubemap)
1930 R_BuildNormalizationCube();
1932 r_texture_fogattenuation = NULL;
1933 //r_texture_fogintensity = NULL;
1934 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1935 memset(&r_waterstate, 0, sizeof(r_waterstate));
1936 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1937 memset(&r_svbsp, 0, sizeof (r_svbsp));
1939 r_refdef.fogmasktable_density = 0;
1942 void gl_main_shutdown(void)
1944 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1945 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1947 // clear out the r_skinframe state
1948 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1949 memset(&r_skinframe, 0, sizeof(r_skinframe));
1952 Mem_Free(r_svbsp.nodes);
1953 memset(&r_svbsp, 0, sizeof (r_svbsp));
1954 R_FreeTexturePool(&r_main_texturepool);
1955 r_texture_blanknormalmap = NULL;
1956 r_texture_white = NULL;
1957 r_texture_grey128 = NULL;
1958 r_texture_black = NULL;
1959 r_texture_whitecube = NULL;
1960 r_texture_normalizationcube = NULL;
1961 r_texture_fogattenuation = NULL;
1962 //r_texture_fogintensity = NULL;
1963 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1964 memset(&r_waterstate, 0, sizeof(r_waterstate));
1968 extern void CL_ParseEntityLump(char *entitystring);
1969 void gl_main_newmap(void)
1971 // FIXME: move this code to client
1973 char *entities, entname[MAX_QPATH];
1976 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1977 l = (int)strlen(entname) - 4;
1978 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1980 memcpy(entname + l, ".ent", 5);
1981 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1983 CL_ParseEntityLump(entities);
1988 if (cl.worldmodel->brush.entities)
1989 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1993 void GL_Main_Init(void)
1995 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1997 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1998 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1999 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2000 if (gamemode == GAME_NEHAHRA)
2002 Cvar_RegisterVariable (&gl_fogenable);
2003 Cvar_RegisterVariable (&gl_fogdensity);
2004 Cvar_RegisterVariable (&gl_fogred);
2005 Cvar_RegisterVariable (&gl_foggreen);
2006 Cvar_RegisterVariable (&gl_fogblue);
2007 Cvar_RegisterVariable (&gl_fogstart);
2008 Cvar_RegisterVariable (&gl_fogend);
2009 Cvar_RegisterVariable (&gl_skyclip);
2011 Cvar_RegisterVariable(&r_depthfirst);
2012 Cvar_RegisterVariable(&r_nearclip);
2013 Cvar_RegisterVariable(&r_showbboxes);
2014 Cvar_RegisterVariable(&r_showsurfaces);
2015 Cvar_RegisterVariable(&r_showtris);
2016 Cvar_RegisterVariable(&r_shownormals);
2017 Cvar_RegisterVariable(&r_showlighting);
2018 Cvar_RegisterVariable(&r_showshadowvolumes);
2019 Cvar_RegisterVariable(&r_showcollisionbrushes);
2020 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2021 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2022 Cvar_RegisterVariable(&r_showdisabledepthtest);
2023 Cvar_RegisterVariable(&r_drawportals);
2024 Cvar_RegisterVariable(&r_drawentities);
2025 Cvar_RegisterVariable(&r_cullentities_trace);
2026 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2027 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2028 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2029 Cvar_RegisterVariable(&r_drawviewmodel);
2030 Cvar_RegisterVariable(&r_speeds);
2031 Cvar_RegisterVariable(&r_fullbrights);
2032 Cvar_RegisterVariable(&r_wateralpha);
2033 Cvar_RegisterVariable(&r_dynamic);
2034 Cvar_RegisterVariable(&r_fullbright);
2035 Cvar_RegisterVariable(&r_shadows);
2036 Cvar_RegisterVariable(&r_shadows_throwdistance);
2037 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2038 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2039 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2040 Cvar_RegisterVariable(&r_fog_exp2);
2041 Cvar_RegisterVariable(&r_textureunits);
2042 Cvar_RegisterVariable(&r_glsl);
2043 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2044 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2045 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2046 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2047 Cvar_RegisterVariable(&r_water);
2048 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2049 Cvar_RegisterVariable(&r_water_clippingplanebias);
2050 Cvar_RegisterVariable(&r_water_refractdistort);
2051 Cvar_RegisterVariable(&r_water_reflectdistort);
2052 Cvar_RegisterVariable(&r_lerpsprites);
2053 Cvar_RegisterVariable(&r_lerpmodels);
2054 Cvar_RegisterVariable(&r_lerplightstyles);
2055 Cvar_RegisterVariable(&r_waterscroll);
2056 Cvar_RegisterVariable(&r_bloom);
2057 Cvar_RegisterVariable(&r_bloom_colorscale);
2058 Cvar_RegisterVariable(&r_bloom_brighten);
2059 Cvar_RegisterVariable(&r_bloom_blur);
2060 Cvar_RegisterVariable(&r_bloom_resolution);
2061 Cvar_RegisterVariable(&r_bloom_colorexponent);
2062 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2063 Cvar_RegisterVariable(&r_hdr);
2064 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2065 Cvar_RegisterVariable(&r_glsl_contrastboost);
2066 Cvar_RegisterVariable(&r_hdr_glowintensity);
2067 Cvar_RegisterVariable(&r_hdr_range);
2068 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2069 Cvar_RegisterVariable(&developer_texturelogging);
2070 Cvar_RegisterVariable(&gl_lightmaps);
2071 Cvar_RegisterVariable(&r_test);
2072 Cvar_RegisterVariable(&r_batchmode);
2073 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2074 Cvar_SetValue("r_fullbrights", 0);
2075 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2077 Cvar_RegisterVariable(&r_track_sprites);
2078 Cvar_RegisterVariable(&r_track_sprites_flags);
2079 Cvar_RegisterVariable(&r_track_sprites_scalew);
2080 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2083 extern void R_Textures_Init(void);
2084 extern void GL_Draw_Init(void);
2085 extern void GL_Main_Init(void);
2086 extern void R_Shadow_Init(void);
2087 extern void R_Sky_Init(void);
2088 extern void GL_Surf_Init(void);
2089 extern void R_Particles_Init(void);
2090 extern void R_Explosion_Init(void);
2091 extern void gl_backend_init(void);
2092 extern void Sbar_Init(void);
2093 extern void R_LightningBeams_Init(void);
2094 extern void Mod_RenderInit(void);
2096 void Render_Init(void)
2108 R_LightningBeams_Init();
2117 extern char *ENGINE_EXTENSIONS;
2120 VID_CheckExtensions();
2122 // LordHavoc: report supported extensions
2123 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2125 // clear to black (loading plaque will be seen over this)
2127 qglClearColor(0,0,0,1);CHECKGLERROR
2128 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2131 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2135 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2137 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2140 p = r_refdef.view.frustum + i;
2145 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2149 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2153 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2157 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2161 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2165 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2169 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2173 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2181 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2185 for (i = 0;i < numplanes;i++)
2192 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2196 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2200 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2204 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2208 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2212 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2216 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2220 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2228 //==================================================================================
2230 static void R_View_UpdateEntityVisible (void)
2233 entity_render_t *ent;
2235 if (!r_drawentities.integer)
2238 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2239 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2241 // worldmodel can check visibility
2242 for (i = 0;i < r_refdef.scene.numentities;i++)
2244 ent = r_refdef.scene.entities[i];
2245 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));
2248 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2250 for (i = 0;i < r_refdef.scene.numentities;i++)
2252 ent = r_refdef.scene.entities[i];
2253 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2255 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))
2256 ent->last_trace_visibility = realtime;
2257 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2258 r_refdef.viewcache.entityvisible[i] = 0;
2265 // no worldmodel or it can't check visibility
2266 for (i = 0;i < r_refdef.scene.numentities;i++)
2268 ent = r_refdef.scene.entities[i];
2269 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));
2274 // only used if skyrendermasked, and normally returns false
2275 int R_DrawBrushModelsSky (void)
2278 entity_render_t *ent;
2280 if (!r_drawentities.integer)
2284 for (i = 0;i < r_refdef.scene.numentities;i++)
2286 if (!r_refdef.viewcache.entityvisible[i])
2288 ent = r_refdef.scene.entities[i];
2289 if (!ent->model || !ent->model->DrawSky)
2291 ent->model->DrawSky(ent);
2297 static void R_DrawNoModel(entity_render_t *ent);
2298 static void R_DrawModels(void)
2301 entity_render_t *ent;
2303 if (!r_drawentities.integer)
2306 for (i = 0;i < r_refdef.scene.numentities;i++)
2308 if (!r_refdef.viewcache.entityvisible[i])
2310 ent = r_refdef.scene.entities[i];
2311 r_refdef.stats.entities++;
2312 if (ent->model && ent->model->Draw != NULL)
2313 ent->model->Draw(ent);
2319 static void R_DrawModelsDepth(void)
2322 entity_render_t *ent;
2324 if (!r_drawentities.integer)
2327 for (i = 0;i < r_refdef.scene.numentities;i++)
2329 if (!r_refdef.viewcache.entityvisible[i])
2331 ent = r_refdef.scene.entities[i];
2332 if (ent->model && ent->model->DrawDepth != NULL)
2333 ent->model->DrawDepth(ent);
2337 static void R_DrawModelsDebug(void)
2340 entity_render_t *ent;
2342 if (!r_drawentities.integer)
2345 for (i = 0;i < r_refdef.scene.numentities;i++)
2347 if (!r_refdef.viewcache.entityvisible[i])
2349 ent = r_refdef.scene.entities[i];
2350 if (ent->model && ent->model->DrawDebug != NULL)
2351 ent->model->DrawDebug(ent);
2355 static void R_DrawModelsAddWaterPlanes(void)
2358 entity_render_t *ent;
2360 if (!r_drawentities.integer)
2363 for (i = 0;i < r_refdef.scene.numentities;i++)
2365 if (!r_refdef.viewcache.entityvisible[i])
2367 ent = r_refdef.scene.entities[i];
2368 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2369 ent->model->DrawAddWaterPlanes(ent);
2373 static void R_View_SetFrustum(void)
2376 double slopex, slopey;
2378 // break apart the view matrix into vectors for various purposes
2379 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
2380 VectorNegate(r_refdef.view.left, r_refdef.view.right);
2383 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2384 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2385 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2386 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2387 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2388 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2389 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2390 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2391 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2392 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2393 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2394 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2398 zNear = r_refdef.nearclip;
2399 nudge = 1.0 - 1.0 / (1<<23);
2400 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2401 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2402 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2403 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2404 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2405 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2406 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2407 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2413 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2414 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2415 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2416 r_refdef.view.frustum[0].dist = m[15] - m[12];
2418 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2419 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2420 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2421 r_refdef.view.frustum[1].dist = m[15] + m[12];
2423 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2424 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2425 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2426 r_refdef.view.frustum[2].dist = m[15] - m[13];
2428 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2429 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2430 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2431 r_refdef.view.frustum[3].dist = m[15] + m[13];
2433 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2434 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2435 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2436 r_refdef.view.frustum[4].dist = m[15] - m[14];
2438 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2439 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2440 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2441 r_refdef.view.frustum[5].dist = m[15] + m[14];
2444 if (r_refdef.view.useperspective)
2446 slopex = 1.0 / r_refdef.view.frustum_x;
2447 slopey = 1.0 / r_refdef.view.frustum_y;
2448 VectorMA(r_refdef.view.forward, -slopex, r_refdef.view.left, r_refdef.view.frustum[0].normal);
2449 VectorMA(r_refdef.view.forward, slopex, r_refdef.view.left, r_refdef.view.frustum[1].normal);
2450 VectorMA(r_refdef.view.forward, -slopey, r_refdef.view.up , r_refdef.view.frustum[2].normal);
2451 VectorMA(r_refdef.view.forward, slopey, r_refdef.view.up , r_refdef.view.frustum[3].normal);
2452 VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
2454 // Leaving those out was a mistake, those were in the old code, and they
2455 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2456 // I couldn't reproduce it after adding those normalizations. --blub
2457 VectorNormalize(r_refdef.view.frustum[0].normal);
2458 VectorNormalize(r_refdef.view.frustum[1].normal);
2459 VectorNormalize(r_refdef.view.frustum[2].normal);
2460 VectorNormalize(r_refdef.view.frustum[3].normal);
2462 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2463 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]);
2464 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]);
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[2]);
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[3]);
2468 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2469 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2470 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2471 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2472 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2476 VectorScale(r_refdef.view.left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2477 VectorScale(r_refdef.view.left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2478 VectorScale(r_refdef.view.up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2479 VectorScale(r_refdef.view.up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2480 VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
2481 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2482 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2483 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2484 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2485 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2487 r_refdef.view.numfrustumplanes = 5;
2489 if (r_refdef.view.useclipplane)
2491 r_refdef.view.numfrustumplanes = 6;
2492 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2495 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2496 PlaneClassify(r_refdef.view.frustum + i);
2498 // LordHavoc: note to all quake engine coders, Quake had a special case
2499 // for 90 degrees which assumed a square view (wrong), so I removed it,
2500 // Quake2 has it disabled as well.
2502 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2503 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, r_refdef.view.up, r_refdef.view.forward, -(90 - r_refdef.fov_x / 2));
2504 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2505 //PlaneClassify(&frustum[0]);
2507 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2508 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, r_refdef.view.up, r_refdef.view.forward, (90 - r_refdef.fov_x / 2));
2509 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2510 //PlaneClassify(&frustum[1]);
2512 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2513 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, r_refdef.view.left, r_refdef.view.forward, -(90 - r_refdef.fov_y / 2));
2514 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2515 //PlaneClassify(&frustum[2]);
2517 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2518 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, r_refdef.view.left, r_refdef.view.forward, (90 - r_refdef.fov_y / 2));
2519 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2520 //PlaneClassify(&frustum[3]);
2523 //VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
2524 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2525 //PlaneClassify(&frustum[4]);
2528 void R_View_Update(void)
2530 R_View_SetFrustum();
2531 R_View_WorldVisibility(r_refdef.view.useclipplane);
2532 R_View_UpdateEntityVisible();
2535 void R_SetupView(void)
2537 if (!r_refdef.view.useperspective)
2538 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);
2539 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2540 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2542 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2544 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2546 if (r_refdef.view.useclipplane)
2548 // LordHavoc: couldn't figure out how to make this approach the
2549 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2550 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2551 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2552 dist = r_refdef.view.clipplane.dist;
2553 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2557 void R_ResetViewRendering2D(void)
2559 if (gl_support_fragment_shader)
2561 qglUseProgramObjectARB(0);CHECKGLERROR
2566 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2567 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2568 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2569 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2570 GL_Color(1, 1, 1, 1);
2571 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2572 GL_BlendFunc(GL_ONE, GL_ZERO);
2573 GL_AlphaTest(false);
2574 GL_ScissorTest(false);
2575 GL_DepthMask(false);
2576 GL_DepthRange(0, 1);
2577 GL_DepthTest(false);
2578 R_Mesh_Matrix(&identitymatrix);
2579 R_Mesh_ResetTextureState();
2580 GL_PolygonOffset(0, 0);
2581 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2582 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2583 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2584 qglStencilMask(~0);CHECKGLERROR
2585 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2586 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2587 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2590 void R_ResetViewRendering3D(void)
2592 if (gl_support_fragment_shader)
2594 qglUseProgramObjectARB(0);CHECKGLERROR
2599 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2600 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2602 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2603 GL_Color(1, 1, 1, 1);
2604 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2605 GL_BlendFunc(GL_ONE, GL_ZERO);
2606 GL_AlphaTest(false);
2607 GL_ScissorTest(true);
2609 GL_DepthRange(0, 1);
2611 R_Mesh_Matrix(&identitymatrix);
2612 R_Mesh_ResetTextureState();
2613 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2614 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2615 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2616 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2617 qglStencilMask(~0);CHECKGLERROR
2618 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2619 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2620 GL_CullFace(r_refdef.view.cullface_back);
2624 R_Bloom_SetupShader(
2626 "// written by Forest 'LordHavoc' Hale\n"
2628 "// common definitions between vertex shader and fragment shader:\n"
2630 "#ifdef __GLSL_CG_DATA_TYPES\n"
2631 "#define myhalf half\n"
2632 "#define myhalf2 half2\n"
2633 "#define myhalf3 half3\n"
2634 "#define myhalf4 half4\n"
2636 "#define myhalf float\n"
2637 "#define myhalf2 vec2\n"
2638 "#define myhalf3 vec3\n"
2639 "#define myhalf4 vec4\n"
2642 "varying vec2 ScreenTexCoord;\n"
2643 "varying vec2 BloomTexCoord;\n"
2648 "// vertex shader specific:\n"
2649 "#ifdef VERTEX_SHADER\n"
2653 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2654 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2655 " // transform vertex to camera space, using ftransform to match non-VS\n"
2657 " gl_Position = ftransform();\n"
2660 "#endif // VERTEX_SHADER\n"
2665 "// fragment shader specific:\n"
2666 "#ifdef FRAGMENT_SHADER\n"
2671 " myhalf3 color = myhalf3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2672 " for (x = -BLUR_X;x <= BLUR_X;x++)
2673 " color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2674 " color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2675 " color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2676 " color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2678 " gl_FragColor = vec4(color);\n"
2681 "#endif // FRAGMENT_SHADER\n"
2684 void R_RenderScene(qboolean addwaterplanes);
2686 static void R_Water_StartFrame(void)
2689 int waterwidth, waterheight, texturewidth, textureheight;
2690 r_waterstate_waterplane_t *p;
2692 // set waterwidth and waterheight to the water resolution that will be
2693 // used (often less than the screen resolution for faster rendering)
2694 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
2695 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
2697 // calculate desired texture sizes
2698 // can't use water if the card does not support the texture size
2699 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2700 texturewidth = textureheight = waterwidth = waterheight = 0;
2701 else if (gl_support_arb_texture_non_power_of_two)
2703 texturewidth = waterwidth;
2704 textureheight = waterheight;
2708 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2709 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2712 // allocate textures as needed
2713 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2715 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2716 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2718 if (p->texture_refraction)
2719 R_FreeTexture(p->texture_refraction);
2720 p->texture_refraction = NULL;
2721 if (p->texture_reflection)
2722 R_FreeTexture(p->texture_reflection);
2723 p->texture_reflection = NULL;
2725 memset(&r_waterstate, 0, sizeof(r_waterstate));
2726 r_waterstate.waterwidth = waterwidth;
2727 r_waterstate.waterheight = waterheight;
2728 r_waterstate.texturewidth = texturewidth;
2729 r_waterstate.textureheight = textureheight;
2732 if (r_waterstate.waterwidth)
2734 r_waterstate.enabled = true;
2736 // set up variables that will be used in shader setup
2737 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2738 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2739 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2740 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2743 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2744 r_waterstate.numwaterplanes = 0;
2747 static void R_Water_AddWaterPlane(msurface_t *surface)
2749 int triangleindex, planeindex;
2754 r_waterstate_waterplane_t *p;
2755 // just use the first triangle with a valid normal for any decisions
2756 VectorClear(normal);
2757 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2759 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2760 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2761 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2762 TriangleNormal(vert[0], vert[1], vert[2], normal);
2763 if (VectorLength2(normal) >= 0.001)
2767 // find a matching plane if there is one
2768 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2769 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2771 if (planeindex >= r_waterstate.maxwaterplanes)
2772 return; // nothing we can do, out of planes
2774 // if this triangle does not fit any known plane rendered this frame, add one
2775 if (planeindex >= r_waterstate.numwaterplanes)
2777 // store the new plane
2778 r_waterstate.numwaterplanes++;
2779 VectorCopy(normal, p->plane.normal);
2780 VectorNormalize(p->plane.normal);
2781 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2782 PlaneClassify(&p->plane);
2783 // flip the plane if it does not face the viewer
2784 if (PlaneDiff(r_refdef.view.origin, &p->plane) < 0)
2786 VectorNegate(p->plane.normal, p->plane.normal);
2787 p->plane.dist *= -1;
2788 PlaneClassify(&p->plane);
2790 // clear materialflags and pvs
2791 p->materialflags = 0;
2792 p->pvsvalid = false;
2794 // merge this surface's materialflags into the waterplane
2795 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2796 // merge this surface's PVS into the waterplane
2797 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
2798 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
2799 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
2801 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2806 static void R_Water_ProcessPlanes(void)
2808 r_refdef_view_t originalview;
2810 r_waterstate_waterplane_t *p;
2812 originalview = r_refdef.view;
2814 // make sure enough textures are allocated
2815 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2817 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2819 if (!p->texture_refraction)
2820 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);
2821 if (!p->texture_refraction)
2825 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2827 if (!p->texture_reflection)
2828 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);
2829 if (!p->texture_reflection)
2835 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2837 r_refdef.view.showdebug = false;
2838 r_refdef.view.width = r_waterstate.waterwidth;
2839 r_refdef.view.height = r_waterstate.waterheight;
2840 r_refdef.view.useclipplane = true;
2841 r_waterstate.renderingscene = true;
2843 // render the normal view scene and copy into texture
2844 // (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)
2845 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2847 r_refdef.view.clipplane = p->plane;
2848 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
2849 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
2850 PlaneClassify(&r_refdef.view.clipplane);
2852 R_RenderScene(false);
2854 // copy view into the screen texture
2855 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2856 GL_ActiveTexture(0);
2858 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
2861 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2863 // render reflected scene and copy into texture
2864 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2865 r_refdef.view.clipplane = p->plane;
2866 // reverse the cullface settings for this render
2867 r_refdef.view.cullface_front = GL_FRONT;
2868 r_refdef.view.cullface_back = GL_BACK;
2869 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
2871 r_refdef.view.usecustompvs = true;
2873 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
2875 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
2878 R_ResetViewRendering3D();
2879 R_ClearScreen(r_refdef.fogenabled);
2880 if (r_timereport_active)
2881 R_TimeReport("viewclear");
2883 R_RenderScene(false);
2885 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2886 GL_ActiveTexture(0);
2888 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
2890 R_ResetViewRendering3D();
2891 R_ClearScreen(r_refdef.fogenabled);
2892 if (r_timereport_active)
2893 R_TimeReport("viewclear");
2896 r_refdef.view = originalview;
2897 r_refdef.view.clear = true;
2898 r_waterstate.renderingscene = false;
2902 r_refdef.view = originalview;
2903 r_waterstate.renderingscene = false;
2904 Cvar_SetValueQuick(&r_water, 0);
2905 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
2909 void R_Bloom_StartFrame(void)
2911 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2913 // set bloomwidth and bloomheight to the bloom resolution that will be
2914 // used (often less than the screen resolution for faster rendering)
2915 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
2916 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
2917 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
2919 // calculate desired texture sizes
2920 if (gl_support_arb_texture_non_power_of_two)
2922 screentexturewidth = r_refdef.view.width;
2923 screentextureheight = r_refdef.view.height;
2924 bloomtexturewidth = r_bloomstate.bloomwidth;
2925 bloomtextureheight = r_bloomstate.bloomheight;
2929 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2930 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2931 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2932 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2937 screentexturewidth = screentextureheight = 0;
2939 else if (r_bloom.integer)
2944 screentexturewidth = screentextureheight = 0;
2945 bloomtexturewidth = bloomtextureheight = 0;
2948 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)
2950 // can't use bloom if the parameters are too weird
2951 // can't use bloom if the card does not support the texture size
2952 if (r_bloomstate.texture_screen)
2953 R_FreeTexture(r_bloomstate.texture_screen);
2954 if (r_bloomstate.texture_bloom)
2955 R_FreeTexture(r_bloomstate.texture_bloom);
2956 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2960 r_bloomstate.enabled = true;
2961 r_bloomstate.hdr = r_hdr.integer != 0;
2963 // allocate textures as needed
2964 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2966 if (r_bloomstate.texture_screen)
2967 R_FreeTexture(r_bloomstate.texture_screen);
2968 r_bloomstate.texture_screen = NULL;
2969 r_bloomstate.screentexturewidth = screentexturewidth;
2970 r_bloomstate.screentextureheight = screentextureheight;
2971 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2972 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);
2974 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2976 if (r_bloomstate.texture_bloom)
2977 R_FreeTexture(r_bloomstate.texture_bloom);
2978 r_bloomstate.texture_bloom = NULL;
2979 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2980 r_bloomstate.bloomtextureheight = bloomtextureheight;
2981 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2982 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);
2985 // set up a texcoord array for the full resolution screen image
2986 // (we have to keep this around to copy back during final render)
2987 r_bloomstate.screentexcoord2f[0] = 0;
2988 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
2989 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
2990 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
2991 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
2992 r_bloomstate.screentexcoord2f[5] = 0;
2993 r_bloomstate.screentexcoord2f[6] = 0;
2994 r_bloomstate.screentexcoord2f[7] = 0;
2996 // set up a texcoord array for the reduced resolution bloom image
2997 // (which will be additive blended over the screen image)
2998 r_bloomstate.bloomtexcoord2f[0] = 0;
2999 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3000 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3001 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3002 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3003 r_bloomstate.bloomtexcoord2f[5] = 0;
3004 r_bloomstate.bloomtexcoord2f[6] = 0;
3005 r_bloomstate.bloomtexcoord2f[7] = 0;
3008 void R_Bloom_CopyScreenTexture(float colorscale)
3010 r_refdef.stats.bloom++;
3012 R_ResetViewRendering2D();
3013 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3014 R_Mesh_ColorPointer(NULL, 0, 0);
3015 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3016 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3018 // copy view into the screen texture
3019 GL_ActiveTexture(0);
3021 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
3022 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3024 // now scale it down to the bloom texture size
3026 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3027 GL_BlendFunc(GL_ONE, GL_ZERO);
3028 GL_Color(colorscale, colorscale, colorscale, 1);
3029 // TODO: optimize with multitexture or GLSL
3030 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3031 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3033 // we now have a bloom image in the framebuffer
3034 // copy it into the bloom image texture for later processing
3035 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3036 GL_ActiveTexture(0);
3038 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
3039 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3042 void R_Bloom_CopyHDRTexture(void)
3044 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3045 GL_ActiveTexture(0);
3047 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
3048 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3051 void R_Bloom_MakeTexture(void)
3054 float xoffset, yoffset, r, brighten;
3056 r_refdef.stats.bloom++;
3058 R_ResetViewRendering2D();
3059 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3060 R_Mesh_ColorPointer(NULL, 0, 0);
3062 // we have a bloom image in the framebuffer
3064 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3066 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3069 r = bound(0, r_bloom_colorexponent.value / x, 1);
3070 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3071 GL_Color(r, r, r, 1);
3072 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3073 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3074 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3075 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3077 // copy the vertically blurred bloom view to a texture
3078 GL_ActiveTexture(0);
3080 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
3081 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3084 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3085 brighten = r_bloom_brighten.value;
3087 brighten *= r_hdr_range.value;
3088 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3089 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3091 for (dir = 0;dir < 2;dir++)
3093 // blend on at multiple vertical offsets to achieve a vertical blur
3094 // TODO: do offset blends using GLSL
3095 GL_BlendFunc(GL_ONE, GL_ZERO);
3096 for (x = -range;x <= range;x++)
3098 if (!dir){xoffset = 0;yoffset = x;}
3099 else {xoffset = x;yoffset = 0;}
3100 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3101 yoffset /= (float)r_bloomstate.bloomtextureheight;
3102 // compute a texcoord array with the specified x and y offset
3103 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3104 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3105 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3106 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3107 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3108 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3109 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3110 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3111 // this r value looks like a 'dot' particle, fading sharply to
3112 // black at the edges
3113 // (probably not realistic but looks good enough)
3114 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3115 //r = (dir ? 1.0f : brighten)/(range*2+1);
3116 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3117 GL_Color(r, r, r, 1);
3118 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3119 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3120 GL_BlendFunc(GL_ONE, GL_ONE);
3123 // copy the vertically blurred bloom view to a texture
3124 GL_ActiveTexture(0);
3126 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
3127 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3130 // apply subtract last
3131 // (just like it would be in a GLSL shader)
3132 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3134 GL_BlendFunc(GL_ONE, GL_ZERO);
3135 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3136 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3137 GL_Color(1, 1, 1, 1);
3138 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3139 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3141 GL_BlendFunc(GL_ONE, GL_ONE);
3142 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3143 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3144 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3145 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3146 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3147 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3148 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3150 // copy the darkened bloom view to a texture
3151 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3152 GL_ActiveTexture(0);
3154 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
3155 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3159 void R_HDR_RenderBloomTexture(void)
3161 int oldwidth, oldheight;
3162 float oldcolorscale;
3164 oldcolorscale = r_refdef.view.colorscale;
3165 oldwidth = r_refdef.view.width;
3166 oldheight = r_refdef.view.height;
3167 r_refdef.view.width = r_bloomstate.bloomwidth;
3168 r_refdef.view.height = r_bloomstate.bloomheight;
3170 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3171 // TODO: add exposure compensation features
3172 // TODO: add fp16 framebuffer support
3174 r_refdef.view.showdebug = false;
3175 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3177 R_ClearScreen(r_refdef.fogenabled);
3178 if (r_timereport_active)
3179 R_TimeReport("HDRclear");
3181 r_waterstate.numwaterplanes = 0;
3182 R_RenderScene(r_waterstate.enabled);
3183 r_refdef.view.showdebug = true;
3185 R_ResetViewRendering2D();
3187 R_Bloom_CopyHDRTexture();
3188 R_Bloom_MakeTexture();
3190 // restore the view settings
3191 r_refdef.view.width = oldwidth;
3192 r_refdef.view.height = oldheight;
3193 r_refdef.view.colorscale = oldcolorscale;
3195 R_ResetViewRendering3D();
3197 R_ClearScreen(r_refdef.fogenabled);
3198 if (r_timereport_active)
3199 R_TimeReport("viewclear");
3202 static void R_BlendView(void)
3204 if (r_bloomstate.enabled && r_bloomstate.hdr)
3206 // render high dynamic range bloom effect
3207 // the bloom texture was made earlier this render, so we just need to
3208 // blend it onto the screen...
3209 R_ResetViewRendering2D();
3210 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3211 R_Mesh_ColorPointer(NULL, 0, 0);
3212 GL_Color(1, 1, 1, 1);
3213 GL_BlendFunc(GL_ONE, GL_ONE);
3214 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3215 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3216 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3217 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3219 else if (r_bloomstate.enabled)
3221 // render simple bloom effect
3222 // copy the screen and shrink it and darken it for the bloom process
3223 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
3224 // make the bloom texture
3225 R_Bloom_MakeTexture();
3226 // put the original screen image back in place and blend the bloom
3228 R_ResetViewRendering2D();
3229 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3230 R_Mesh_ColorPointer(NULL, 0, 0);
3231 GL_Color(1, 1, 1, 1);
3232 GL_BlendFunc(GL_ONE, GL_ZERO);
3233 // do both in one pass if possible
3234 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3235 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3236 if (r_textureunits.integer >= 2 && gl_combine.integer)
3238 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
3239 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3240 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3244 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3245 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3246 // now blend on the bloom texture
3247 GL_BlendFunc(GL_ONE, GL_ONE);
3248 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3249 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3251 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3252 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3254 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3256 // apply a color tint to the whole view
3257 R_ResetViewRendering2D();
3258 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3259 R_Mesh_ColorPointer(NULL, 0, 0);
3260 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3261 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3262 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3266 void R_RenderScene(qboolean addwaterplanes);
3268 matrix4x4_t r_waterscrollmatrix;
3270 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3272 if (r_refdef.fog_density)
3274 r_refdef.fogcolor[0] = r_refdef.fog_red;
3275 r_refdef.fogcolor[1] = r_refdef.fog_green;
3276 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3280 VectorCopy(r_refdef.fogcolor, fogvec);
3281 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3283 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3284 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3285 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3286 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3288 // color.rgb *= ContrastBoost * SceneBrightness;
3289 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3290 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3291 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3292 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3297 void R_UpdateVariables(void)
3301 r_refdef.farclip = 4096;
3302 if (r_refdef.scene.worldmodel)
3303 r_refdef.farclip += VectorDistance(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3304 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3306 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3307 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3308 r_refdef.polygonfactor = 0;
3309 r_refdef.polygonoffset = 0;
3310 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3311 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3313 r_refdef.rtworld = r_shadow_realtime_world.integer;
3314 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3315 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3316 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3317 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3318 if (r_showsurfaces.integer)
3320 r_refdef.rtworld = false;
3321 r_refdef.rtworldshadows = false;
3322 r_refdef.rtdlight = false;
3323 r_refdef.rtdlightshadows = false;
3324 r_refdef.lightmapintensity = 0;
3327 if (gamemode == GAME_NEHAHRA)
3329 if (gl_fogenable.integer)
3331 r_refdef.oldgl_fogenable = true;
3332 r_refdef.fog_density = gl_fogdensity.value;
3333 r_refdef.fog_red = gl_fogred.value;
3334 r_refdef.fog_green = gl_foggreen.value;
3335 r_refdef.fog_blue = gl_fogblue.value;
3336 r_refdef.fog_alpha = 1;
3337 r_refdef.fog_start = 0;
3338 r_refdef.fog_end = gl_skyclip.value;
3340 else if (r_refdef.oldgl_fogenable)
3342 r_refdef.oldgl_fogenable = false;
3343 r_refdef.fog_density = 0;
3344 r_refdef.fog_red = 0;
3345 r_refdef.fog_green = 0;
3346 r_refdef.fog_blue = 0;
3347 r_refdef.fog_alpha = 0;
3348 r_refdef.fog_start = 0;
3349 r_refdef.fog_end = 0;
3353 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3354 r_refdef.fog_start = max(0, r_refdef.fog_start);
3355 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3357 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3359 if (r_refdef.fog_density)
3361 r_refdef.fogenabled = true;
3362 // this is the point where the fog reaches 0.9986 alpha, which we
3363 // consider a good enough cutoff point for the texture
3364 // (0.9986 * 256 == 255.6)
3365 if (r_fog_exp2.integer)
3366 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3368 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3369 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3370 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3371 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3372 // fog color was already set
3373 // update the fog texture
3374 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)
3375 R_BuildFogTexture();
3378 r_refdef.fogenabled = false;
3386 void R_RenderView(void)
3388 if (!r_refdef.scene.entities/* || !r_refdef.scene.worldmodel*/)
3389 return; //Host_Error ("R_RenderView: NULL worldmodel");
3391 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3393 R_Shadow_UpdateWorldLightSelection();
3395 R_Bloom_StartFrame();
3396 R_Water_StartFrame();
3399 if (r_timereport_active)
3400 R_TimeReport("viewsetup");
3402 R_ResetViewRendering3D();
3404 if (r_refdef.view.clear || r_refdef.fogenabled)
3406 R_ClearScreen(r_refdef.fogenabled);
3407 if (r_timereport_active)
3408 R_TimeReport("viewclear");
3410 r_refdef.view.clear = true;
3412 r_refdef.view.showdebug = true;
3414 // this produces a bloom texture to be used in R_BlendView() later
3416 R_HDR_RenderBloomTexture();
3418 r_waterstate.numwaterplanes = 0;
3419 R_RenderScene(r_waterstate.enabled);
3422 if (r_timereport_active)
3423 R_TimeReport("blendview");
3425 GL_Scissor(0, 0, vid.width, vid.height);
3426 GL_ScissorTest(false);
3430 extern void R_DrawLightningBeams (void);
3431 extern void VM_CL_AddPolygonsToMeshQueue (void);
3432 extern void R_DrawPortals (void);
3433 extern cvar_t cl_locs_show;
3434 static void R_DrawLocs(void);
3435 static void R_DrawEntityBBoxes(void);
3436 void R_RenderScene(qboolean addwaterplanes)
3438 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3443 R_ResetViewRendering3D();
3446 if (r_timereport_active)
3447 R_TimeReport("watervis");
3449 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3451 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3452 if (r_timereport_active)
3453 R_TimeReport("waterworld");
3456 // don't let sound skip if going slow
3457 if (r_refdef.scene.extraupdate)
3460 R_DrawModelsAddWaterPlanes();
3461 if (r_timereport_active)
3462 R_TimeReport("watermodels");
3464 R_Water_ProcessPlanes();
3465 if (r_timereport_active)
3466 R_TimeReport("waterscenes");
3469 R_ResetViewRendering3D();
3471 // don't let sound skip if going slow
3472 if (r_refdef.scene.extraupdate)
3475 R_MeshQueue_BeginScene();
3480 if (r_timereport_active)
3481 R_TimeReport("visibility");
3483 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);
3485 if (cl.csqc_vidvars.drawworld)
3487 // don't let sound skip if going slow
3488 if (r_refdef.scene.extraupdate)
3491 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
3493 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
3494 if (r_timereport_active)
3495 R_TimeReport("worldsky");
3498 if (R_DrawBrushModelsSky() && r_timereport_active)
3499 R_TimeReport("bmodelsky");
3502 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
3504 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
3505 if (r_timereport_active)
3506 R_TimeReport("worlddepth");
3508 if (r_depthfirst.integer >= 2)
3510 R_DrawModelsDepth();
3511 if (r_timereport_active)
3512 R_TimeReport("modeldepth");
3515 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
3517 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
3518 if (r_timereport_active)
3519 R_TimeReport("world");
3522 // don't let sound skip if going slow
3523 if (r_refdef.scene.extraupdate)
3527 if (r_timereport_active)
3528 R_TimeReport("models");
3530 // don't let sound skip if going slow
3531 if (r_refdef.scene.extraupdate)
3534 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3536 R_DrawModelShadows();
3538 R_ResetViewRendering3D();
3540 // don't let sound skip if going slow
3541 if (r_refdef.scene.extraupdate)
3545 R_ShadowVolumeLighting(false);
3546 if (r_timereport_active)
3547 R_TimeReport("rtlights");
3549 // don't let sound skip if going slow
3550 if (r_refdef.scene.extraupdate)
3553 if (cl.csqc_vidvars.drawworld)
3555 R_DrawLightningBeams();
3556 if (r_timereport_active)
3557 R_TimeReport("lightning");
3560 if (r_timereport_active)
3561 R_TimeReport("decals");
3564 if (r_timereport_active)
3565 R_TimeReport("particles");
3568 if (r_timereport_active)
3569 R_TimeReport("explosions");
3572 if (gl_support_fragment_shader)
3574 qglUseProgramObjectARB(0);CHECKGLERROR
3576 VM_CL_AddPolygonsToMeshQueue();
3578 if (r_refdef.view.showdebug)
3580 if (cl_locs_show.integer)
3583 if (r_timereport_active)
3584 R_TimeReport("showlocs");
3587 if (r_drawportals.integer)
3590 if (r_timereport_active)
3591 R_TimeReport("portals");
3594 if (r_showbboxes.value > 0)
3596 R_DrawEntityBBoxes();
3597 if (r_timereport_active)
3598 R_TimeReport("bboxes");
3602 if (gl_support_fragment_shader)
3604 qglUseProgramObjectARB(0);CHECKGLERROR
3606 R_MeshQueue_RenderTransparent();
3607 if (r_timereport_active)
3608 R_TimeReport("drawtrans");
3610 if (gl_support_fragment_shader)
3612 qglUseProgramObjectARB(0);CHECKGLERROR
3615 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))
3617 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
3618 if (r_timereport_active)
3619 R_TimeReport("worlddebug");
3620 R_DrawModelsDebug();
3621 if (r_timereport_active)
3622 R_TimeReport("modeldebug");
3625 if (gl_support_fragment_shader)
3627 qglUseProgramObjectARB(0);CHECKGLERROR
3630 if (cl.csqc_vidvars.drawworld)
3633 if (r_timereport_active)
3634 R_TimeReport("coronas");
3637 // don't let sound skip if going slow
3638 if (r_refdef.scene.extraupdate)
3641 R_ResetViewRendering2D();
3644 static const int bboxelements[36] =
3654 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3657 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3658 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3659 GL_DepthMask(false);
3660 GL_DepthRange(0, 1);
3661 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3662 R_Mesh_Matrix(&identitymatrix);
3663 R_Mesh_ResetTextureState();
3665 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3666 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3667 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3668 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3669 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3670 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3671 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3672 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3673 R_FillColors(color4f, 8, cr, cg, cb, ca);
3674 if (r_refdef.fogenabled)
3676 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3678 f1 = FogPoint_World(v);
3680 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3681 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3682 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3685 R_Mesh_VertexPointer(vertex3f, 0, 0);
3686 R_Mesh_ColorPointer(color4f, 0, 0);
3687 R_Mesh_ResetTextureState();
3688 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3691 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3695 prvm_edict_t *edict;
3696 // this function draws bounding boxes of server entities
3700 for (i = 0;i < numsurfaces;i++)
3702 edict = PRVM_EDICT_NUM(surfacelist[i]);
3703 switch ((int)edict->fields.server->solid)
3705 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3706 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3707 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3708 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3709 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3710 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3712 color[3] *= r_showbboxes.value;
3713 color[3] = bound(0, color[3], 1);
3714 GL_DepthTest(!r_showdisabledepthtest.integer);
3715 GL_CullFace(r_refdef.view.cullface_front);
3716 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3721 static void R_DrawEntityBBoxes(void)
3724 prvm_edict_t *edict;
3726 // this function draws bounding boxes of server entities
3730 for (i = 0;i < prog->num_edicts;i++)
3732 edict = PRVM_EDICT_NUM(i);
3733 if (edict->priv.server->free)
3735 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3736 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3741 int nomodelelements[24] =
3753 float nomodelvertex3f[6*3] =
3763 float nomodelcolor4f[6*4] =
3765 0.0f, 0.0f, 0.5f, 1.0f,
3766 0.0f, 0.0f, 0.5f, 1.0f,
3767 0.0f, 0.5f, 0.0f, 1.0f,
3768 0.0f, 0.5f, 0.0f, 1.0f,
3769 0.5f, 0.0f, 0.0f, 1.0f,
3770 0.5f, 0.0f, 0.0f, 1.0f
3773 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3778 // this is only called once per entity so numsurfaces is always 1, and
3779 // surfacelist is always {0}, so this code does not handle batches
3780 R_Mesh_Matrix(&ent->matrix);
3782 if (ent->flags & EF_ADDITIVE)
3784 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3785 GL_DepthMask(false);
3787 else if (ent->alpha < 1)
3789 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3790 GL_DepthMask(false);
3794 GL_BlendFunc(GL_ONE, GL_ZERO);
3797 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3798 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3799 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3800 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
3801 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3802 if (r_refdef.fogenabled)
3805 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3806 R_Mesh_ColorPointer(color4f, 0, 0);
3807 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3808 f1 = FogPoint_World(org);
3810 for (i = 0, c = color4f;i < 6;i++, c += 4)
3812 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3813 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3814 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3818 else if (ent->alpha != 1)
3820 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3821 R_Mesh_ColorPointer(color4f, 0, 0);
3822 for (i = 0, c = color4f;i < 6;i++, c += 4)
3826 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3827 R_Mesh_ResetTextureState();
3828 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3831 void R_DrawNoModel(entity_render_t *ent)
3834 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3835 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3836 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3838 // R_DrawNoModelCallback(ent, 0);
3841 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3843 vec3_t right1, right2, diff, normal;
3845 VectorSubtract (org2, org1, normal);
3847 // calculate 'right' vector for start
3848 VectorSubtract (r_refdef.view.origin, org1, diff);
3849 CrossProduct (normal, diff, right1);
3850 VectorNormalize (right1);
3852 // calculate 'right' vector for end
3853 VectorSubtract (r_refdef.view.origin, org2, diff);
3854 CrossProduct (normal, diff, right2);
3855 VectorNormalize (right2);
3857 vert[ 0] = org1[0] + width * right1[0];
3858 vert[ 1] = org1[1] + width * right1[1];
3859 vert[ 2] = org1[2] + width * right1[2];
3860 vert[ 3] = org1[0] - width * right1[0];
3861 vert[ 4] = org1[1] - width * right1[1];
3862 vert[ 5] = org1[2] - width * right1[2];
3863 vert[ 6] = org2[0] - width * right2[0];
3864 vert[ 7] = org2[1] - width * right2[1];
3865 vert[ 8] = org2[2] - width * right2[2];
3866 vert[ 9] = org2[0] + width * right2[0];
3867 vert[10] = org2[1] + width * right2[1];
3868 vert[11] = org2[2] + width * right2[2];
3871 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3873 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)
3878 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
3879 fog = FogPoint_World(origin);
3881 R_Mesh_Matrix(&identitymatrix);
3882 GL_BlendFunc(blendfunc1, blendfunc2);
3888 GL_CullFace(r_refdef.view.cullface_front);
3891 GL_CullFace(r_refdef.view.cullface_back);
3893 GL_DepthMask(false);
3894 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3895 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3896 GL_DepthTest(!depthdisable);
3898 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3899 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3900 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3901 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3902 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3903 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3904 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3905 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3906 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3907 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3908 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3909 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3911 R_Mesh_VertexPointer(vertex3f, 0, 0);
3912 R_Mesh_ColorPointer(NULL, 0, 0);
3913 R_Mesh_ResetTextureState();
3914 R_Mesh_TexBind(0, R_GetTexture(texture));
3915 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3916 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
3917 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
3918 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3920 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3922 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3923 GL_BlendFunc(blendfunc1, GL_ONE);
3925 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
3926 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3930 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3935 VectorSet(v, x, y, z);
3936 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3937 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3939 if (i == mesh->numvertices)
3941 if (mesh->numvertices < mesh->maxvertices)
3943 VectorCopy(v, vertex3f);
3944 mesh->numvertices++;
3946 return mesh->numvertices;
3952 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3956 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3957 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3958 e = mesh->element3i + mesh->numtriangles * 3;
3959 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3961 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3962 if (mesh->numtriangles < mesh->maxtriangles)
3967 mesh->numtriangles++;
3969 element[1] = element[2];
3973 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3977 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3978 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3979 e = mesh->element3i + mesh->numtriangles * 3;
3980 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3982 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3983 if (mesh->numtriangles < mesh->maxtriangles)
3988 mesh->numtriangles++;
3990 element[1] = element[2];
3994 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3995 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3997 int planenum, planenum2;
4000 mplane_t *plane, *plane2;
4002 double temppoints[2][256*3];
4003 // figure out how large a bounding box we need to properly compute this brush
4005 for (w = 0;w < numplanes;w++)
4006 maxdist = max(maxdist, planes[w].dist);
4007 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4008 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4009 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4013 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4014 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4016 if (planenum2 == planenum)
4018 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);
4021 if (tempnumpoints < 3)
4023 // generate elements forming a triangle fan for this polygon
4024 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4028 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)
4030 texturelayer_t *layer;
4031 layer = t->currentlayers + t->currentnumlayers++;
4033 layer->depthmask = depthmask;
4034 layer->blendfunc1 = blendfunc1;
4035 layer->blendfunc2 = blendfunc2;
4036 layer->texture = texture;
4037 layer->texmatrix = *matrix;
4038 layer->color[0] = r * r_refdef.view.colorscale;
4039 layer->color[1] = g * r_refdef.view.colorscale;
4040 layer->color[2] = b * r_refdef.view.colorscale;
4041 layer->color[3] = a;
4044 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4047 index = parms[2] + r_refdef.scene.time * parms[3];
4048 index -= floor(index);
4052 case Q3WAVEFUNC_NONE:
4053 case Q3WAVEFUNC_NOISE:
4054 case Q3WAVEFUNC_COUNT:
4057 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4058 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4059 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4060 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4061 case Q3WAVEFUNC_TRIANGLE:
4063 f = index - floor(index);
4074 return (float)(parms[0] + parms[1] * f);
4077 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4080 model_t *model = ent->model;
4083 q3shaderinfo_layer_tcmod_t *tcmod;
4085 // switch to an alternate material if this is a q1bsp animated material
4087 texture_t *texture = t;
4088 int s = ent->skinnum;
4089 if ((unsigned int)s >= (unsigned int)model->numskins)
4091 if (model->skinscenes)
4093 if (model->skinscenes[s].framecount > 1)
4094 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4096 s = model->skinscenes[s].firstframe;
4099 t = t + s * model->num_surfaces;
4102 // use an alternate animation if the entity's frame is not 0,
4103 // and only if the texture has an alternate animation
4104 if (ent->frame2 != 0 && t->anim_total[1])
4105 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4107 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4109 texture->currentframe = t;
4112 // update currentskinframe to be a qw skin or animation frame
4113 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4115 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4117 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4118 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4119 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);
4121 t->currentskinframe = r_qwskincache_skinframe[i];
4122 if (t->currentskinframe == NULL)
4123 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4125 else if (t->numskinframes >= 2)
4126 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4127 if (t->backgroundnumskinframes >= 2)
4128 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4130 t->currentmaterialflags = t->basematerialflags;
4131 t->currentalpha = ent->alpha;
4132 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4134 t->currentalpha *= r_wateralpha.value;
4136 * FIXME what is this supposed to do?
4137 // if rendering refraction/reflection, disable transparency
4138 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4139 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4142 if(!r_waterstate.enabled)
4143 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4144 if (!(ent->flags & RENDER_LIGHT))
4145 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4146 else if (rsurface.modeltexcoordlightmap2f == NULL)
4148 // pick a model lighting mode
4149 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4150 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4152 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4154 if (ent->effects & EF_ADDITIVE)
4155 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4156 else if (t->currentalpha < 1)
4157 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4158 if (ent->effects & EF_DOUBLESIDED)
4159 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4160 if (ent->effects & EF_NODEPTHTEST)
4161 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4162 if (ent->flags & RENDER_VIEWMODEL)
4163 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4164 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4165 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4167 // make sure that the waterscroll matrix is used on water surfaces when
4168 // there is no tcmod
4169 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4170 t->currenttexmatrix = r_waterscrollmatrix;
4172 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4175 switch(tcmod->tcmod)
4179 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4180 matrix = r_waterscrollmatrix;
4182 matrix = identitymatrix;
4184 case Q3TCMOD_ENTITYTRANSLATE:
4185 // this is used in Q3 to allow the gamecode to control texcoord
4186 // scrolling on the entity, which is not supported in darkplaces yet.
4187 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4189 case Q3TCMOD_ROTATE:
4190 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4191 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4192 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4195 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4197 case Q3TCMOD_SCROLL:
4198 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4200 case Q3TCMOD_STRETCH:
4201 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4202 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4204 case Q3TCMOD_TRANSFORM:
4205 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4206 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4207 VectorSet(tcmat + 6, 0 , 0 , 1);
4208 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4209 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4211 case Q3TCMOD_TURBULENT:
4212 // this is handled in the RSurf_PrepareVertices function
4213 matrix = identitymatrix;
4216 // either replace or concatenate the transformation
4218 t->currenttexmatrix = matrix;
4221 matrix4x4_t temp = t->currenttexmatrix;
4222 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4226 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4227 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4228 t->glosstexture = r_texture_black;
4229 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4230 t->backgroundglosstexture = r_texture_black;
4231 t->specularpower = r_shadow_glossexponent.value;
4232 // TODO: store reference values for these in the texture?
4233 t->specularscale = 0;
4234 if (r_shadow_gloss.integer > 0)
4236 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4238 if (r_shadow_glossintensity.value > 0)
4240 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4241 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4242 t->specularscale = r_shadow_glossintensity.value;
4245 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4247 t->glosstexture = r_texture_white;
4248 t->backgroundglosstexture = r_texture_white;
4249 t->specularscale = r_shadow_gloss2intensity.value;
4253 // lightmaps mode looks bad with dlights using actual texturing, so turn
4254 // off the colormap and glossmap, but leave the normalmap on as it still
4255 // accurately represents the shading involved
4256 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4258 t->basetexture = r_texture_white;
4259 t->specularscale = 0;
4262 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4263 VectorClear(t->dlightcolor);
4264 t->currentnumlayers = 0;
4265 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4267 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4269 int blendfunc1, blendfunc2, depthmask;
4270 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4272 blendfunc1 = GL_SRC_ALPHA;
4273 blendfunc2 = GL_ONE;
4275 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4277 blendfunc1 = GL_SRC_ALPHA;
4278 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4280 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4282 blendfunc1 = t->customblendfunc[0];
4283 blendfunc2 = t->customblendfunc[1];
4287 blendfunc1 = GL_ONE;
4288 blendfunc2 = GL_ZERO;
4290 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4291 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4293 rtexture_t *currentbasetexture;
4295 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4296 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4297 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4298 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4300 // fullbright is not affected by r_refdef.lightmapintensity
4301 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4302 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4303 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]);
4304 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4305 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]);
4309 vec3_t ambientcolor;
4311 // set the color tint used for lights affecting this surface
4312 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4314 // q3bsp has no lightmap updates, so the lightstylevalue that
4315 // would normally be baked into the lightmap must be
4316 // applied to the color
4317 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4318 if (ent->model->type == mod_brushq3)
4319 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4320 colorscale *= r_refdef.lightmapintensity;
4321 VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor);
4322 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4323 // basic lit geometry
4324 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4325 // add pants/shirt if needed
4326 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4327 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]);
4328 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4329 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]);
4330 // now add ambient passes if needed
4331 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4333 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
4334 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4335 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]);
4336 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4337 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]);
4340 if (t->currentskinframe->glow != NULL)
4341 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]);
4342 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4344 // if this is opaque use alpha blend which will darken the earlier
4347 // if this is an alpha blended material, all the earlier passes
4348 // were darkened by fog already, so we only need to add the fog
4349 // color ontop through the fog mask texture
4351 // if this is an additive blended material, all the earlier passes
4352 // were darkened by fog already, and we should not add fog color
4353 // (because the background was not darkened, there is no fog color
4354 // that was lost behind it).
4355 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]);
4362 void R_UpdateAllTextureInfo(entity_render_t *ent)
4366 for (i = 0;i < ent->model->num_texturesperskin;i++)
4367 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4370 rsurfacestate_t rsurface;
4372 void R_Mesh_ResizeArrays(int newvertices)
4375 if (rsurface.array_size >= newvertices)
4377 if (rsurface.array_modelvertex3f)
4378 Mem_Free(rsurface.array_modelvertex3f);
4379 rsurface.array_size = (newvertices + 1023) & ~1023;
4380 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4381 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4382 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4383 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4384 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4385 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4386 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4387 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4388 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4389 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4390 rsurface.array_color4f = base + rsurface.array_size * 27;
4391 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4394 void RSurf_CleanUp(void)
4397 if (rsurface.mode == RSURFMODE_GLSL)
4399 qglUseProgramObjectARB(0);CHECKGLERROR
4401 GL_AlphaTest(false);
4402 rsurface.mode = RSURFMODE_NONE;
4403 rsurface.uselightmaptexture = false;
4404 rsurface.texture = NULL;
4407 void RSurf_ActiveWorldEntity(void)
4409 model_t *model = r_refdef.scene.worldmodel;
4411 if (rsurface.array_size < model->surfmesh.num_vertices)
4412 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4413 rsurface.matrix = identitymatrix;
4414 rsurface.inversematrix = identitymatrix;
4415 R_Mesh_Matrix(&identitymatrix);
4416 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4417 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4418 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4419 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4420 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4421 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4422 rsurface.frameblend[0].frame = 0;
4423 rsurface.frameblend[0].lerp = 1;
4424 rsurface.frameblend[1].frame = 0;
4425 rsurface.frameblend[1].lerp = 0;
4426 rsurface.frameblend[2].frame = 0;
4427 rsurface.frameblend[2].lerp = 0;
4428 rsurface.frameblend[3].frame = 0;
4429 rsurface.frameblend[3].lerp = 0;
4430 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4431 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4432 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4433 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4434 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4435 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4436 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4437 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4438 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4439 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4440 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4441 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4442 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4443 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4444 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4445 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4446 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4447 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4448 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4449 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4450 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4451 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4452 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4453 rsurface.modelelement3i = model->surfmesh.data_element3i;
4454 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4455 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4456 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4457 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4458 rsurface.modelsurfaces = model->data_surfaces;
4459 rsurface.generatedvertex = false;
4460 rsurface.vertex3f = rsurface.modelvertex3f;
4461 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4462 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4463 rsurface.svector3f = rsurface.modelsvector3f;
4464 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4465 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4466 rsurface.tvector3f = rsurface.modeltvector3f;
4467 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4468 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4469 rsurface.normal3f = rsurface.modelnormal3f;
4470 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4471 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4472 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4475 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4477 model_t *model = ent->model;
4479 if (rsurface.array_size < model->surfmesh.num_vertices)
4480 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4481 rsurface.matrix = ent->matrix;
4482 rsurface.inversematrix = ent->inversematrix;
4483 R_Mesh_Matrix(&rsurface.matrix);
4484 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
4485 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4486 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4487 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4488 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4489 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4490 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4491 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4492 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4493 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4494 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4495 rsurface.frameblend[0] = ent->frameblend[0];
4496 rsurface.frameblend[1] = ent->frameblend[1];
4497 rsurface.frameblend[2] = ent->frameblend[2];
4498 rsurface.frameblend[3] = ent->frameblend[3];
4499 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4500 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4501 if (ent->model->brush.submodel)
4503 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4504 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4506 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4510 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4511 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4512 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4513 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4514 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4516 else if (wantnormals)
4518 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4519 rsurface.modelsvector3f = NULL;
4520 rsurface.modeltvector3f = NULL;
4521 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4522 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4526 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4527 rsurface.modelsvector3f = NULL;
4528 rsurface.modeltvector3f = NULL;
4529 rsurface.modelnormal3f = NULL;
4530 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4532 rsurface.modelvertex3f_bufferobject = 0;
4533 rsurface.modelvertex3f_bufferoffset = 0;
4534 rsurface.modelsvector3f_bufferobject = 0;
4535 rsurface.modelsvector3f_bufferoffset = 0;
4536 rsurface.modeltvector3f_bufferobject = 0;
4537 rsurface.modeltvector3f_bufferoffset = 0;
4538 rsurface.modelnormal3f_bufferobject = 0;
4539 rsurface.modelnormal3f_bufferoffset = 0;
4540 rsurface.generatedvertex = true;
4544 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4545 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4546 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4547 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4548 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4549 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4550 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4551 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4552 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4553 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4554 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4555 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4556 rsurface.generatedvertex = false;
4558 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4559 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4560 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4561 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4562 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4563 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4564 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4565 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4566 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4567 rsurface.modelelement3i = model->surfmesh.data_element3i;
4568 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4569 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4570 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4571 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4572 rsurface.modelsurfaces = model->data_surfaces;
4573 rsurface.vertex3f = rsurface.modelvertex3f;
4574 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4575 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4576 rsurface.svector3f = rsurface.modelsvector3f;
4577 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4578 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4579 rsurface.tvector3f = rsurface.modeltvector3f;
4580 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4581 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4582 rsurface.normal3f = rsurface.modelnormal3f;
4583 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4584 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4585 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4588 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4589 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4592 int texturesurfaceindex;
4597 const float *v1, *in_tc;
4599 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4601 q3shaderinfo_deform_t *deform;
4602 // 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
4603 if (rsurface.generatedvertex)
4605 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4606 generatenormals = true;
4607 for (i = 0;i < Q3MAXDEFORMS;i++)
4609 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4611 generatetangents = true;
4612 generatenormals = true;
4614 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4615 generatenormals = true;
4617 if (generatenormals && !rsurface.modelnormal3f)
4619 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4620 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4621 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4622 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4624 if (generatetangents && !rsurface.modelsvector3f)
4626 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4627 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4628 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4629 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4630 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4631 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4632 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);
4635 rsurface.vertex3f = rsurface.modelvertex3f;
4636 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4637 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4638 rsurface.svector3f = rsurface.modelsvector3f;
4639 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4640 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4641 rsurface.tvector3f = rsurface.modeltvector3f;
4642 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4643 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4644 rsurface.normal3f = rsurface.modelnormal3f;
4645 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4646 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4647 // if vertices are deformed (sprite flares and things in maps, possibly
4648 // water waves, bulges and other deformations), generate them into
4649 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4650 // (may be static model data or generated data for an animated model, or
4651 // the previous deform pass)
4652 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4654 switch (deform->deform)
4657 case Q3DEFORM_PROJECTIONSHADOW:
4658 case Q3DEFORM_TEXT0:
4659 case Q3DEFORM_TEXT1:
4660 case Q3DEFORM_TEXT2:
4661 case Q3DEFORM_TEXT3:
4662 case Q3DEFORM_TEXT4:
4663 case Q3DEFORM_TEXT5:
4664 case Q3DEFORM_TEXT6:
4665 case Q3DEFORM_TEXT7:
4668 case Q3DEFORM_AUTOSPRITE:
4669 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4670 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4671 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4672 VectorNormalize(newforward);
4673 VectorNormalize(newright);
4674 VectorNormalize(newup);
4675 // make deformed versions of only the model vertices used by the specified surfaces
4676 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4678 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4679 // a single autosprite surface can contain multiple sprites...
4680 for (j = 0;j < surface->num_vertices - 3;j += 4)
4682 VectorClear(center);
4683 for (i = 0;i < 4;i++)
4684 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4685 VectorScale(center, 0.25f, center);
4686 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4687 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4688 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4689 for (i = 0;i < 4;i++)
4691 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4692 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4695 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);
4696 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);
4698 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4699 rsurface.vertex3f_bufferobject = 0;
4700 rsurface.vertex3f_bufferoffset = 0;
4701 rsurface.svector3f = rsurface.array_deformedsvector3f;
4702 rsurface.svector3f_bufferobject = 0;
4703 rsurface.svector3f_bufferoffset = 0;
4704 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4705 rsurface.tvector3f_bufferobject = 0;
4706 rsurface.tvector3f_bufferoffset = 0;
4707 rsurface.normal3f = rsurface.array_deformednormal3f;
4708 rsurface.normal3f_bufferobject = 0;
4709 rsurface.normal3f_bufferoffset = 0;
4711 case Q3DEFORM_AUTOSPRITE2:
4712 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4713 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4714 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4715 VectorNormalize(newforward);
4716 VectorNormalize(newright);
4717 VectorNormalize(newup);
4718 // make deformed versions of only the model vertices used by the specified surfaces
4719 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4721 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4722 const float *v1, *v2;
4732 memset(shortest, 0, sizeof(shortest));
4733 // a single autosprite surface can contain multiple sprites...
4734 for (j = 0;j < surface->num_vertices - 3;j += 4)
4736 VectorClear(center);
4737 for (i = 0;i < 4;i++)
4738 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4739 VectorScale(center, 0.25f, center);
4740 // find the two shortest edges, then use them to define the
4741 // axis vectors for rotating around the central axis
4742 for (i = 0;i < 6;i++)
4744 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4745 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4747 Debug_PolygonBegin(NULL, 0, false, 0);
4748 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4749 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);
4750 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4753 l = VectorDistance2(v1, v2);
4754 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4756 l += (1.0f / 1024.0f);
4757 if (shortest[0].length2 > l || i == 0)
4759 shortest[1] = shortest[0];
4760 shortest[0].length2 = l;
4761 shortest[0].v1 = v1;
4762 shortest[0].v2 = v2;
4764 else if (shortest[1].length2 > l || i == 1)
4766 shortest[1].length2 = l;
4767 shortest[1].v1 = v1;
4768 shortest[1].v2 = v2;
4771 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4772 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4774 Debug_PolygonBegin(NULL, 0, false, 0);
4775 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4776 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);
4777 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4780 // this calculates the right vector from the shortest edge
4781 // and the up vector from the edge midpoints
4782 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4783 VectorNormalize(right);
4784 VectorSubtract(end, start, up);
4785 VectorNormalize(up);
4786 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4787 //VectorSubtract(rsurface.modelorg, center, forward);
4788 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
4789 VectorNegate(forward, forward);
4790 VectorReflect(forward, 0, up, forward);
4791 VectorNormalize(forward);
4792 CrossProduct(up, forward, newright);
4793 VectorNormalize(newright);
4795 Debug_PolygonBegin(NULL, 0, false, 0);
4796 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);
4797 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4798 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4802 Debug_PolygonBegin(NULL, 0, false, 0);
4803 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4804 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4805 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4808 // rotate the quad around the up axis vector, this is made
4809 // especially easy by the fact we know the quad is flat,
4810 // so we only have to subtract the center position and
4811 // measure distance along the right vector, and then
4812 // multiply that by the newright vector and add back the
4814 // we also need to subtract the old position to undo the
4815 // displacement from the center, which we do with a
4816 // DotProduct, the subtraction/addition of center is also
4817 // optimized into DotProducts here
4818 l = DotProduct(right, center);
4819 for (i = 0;i < 4;i++)
4821 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4822 f = DotProduct(right, v1) - l;
4823 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4826 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);
4827 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);
4829 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4830 rsurface.vertex3f_bufferobject = 0;
4831 rsurface.vertex3f_bufferoffset = 0;
4832 rsurface.svector3f = rsurface.array_deformedsvector3f;
4833 rsurface.svector3f_bufferobject = 0;
4834 rsurface.svector3f_bufferoffset = 0;
4835 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4836 rsurface.tvector3f_bufferobject = 0;
4837 rsurface.tvector3f_bufferoffset = 0;
4838 rsurface.normal3f = rsurface.array_deformednormal3f;
4839 rsurface.normal3f_bufferobject = 0;
4840 rsurface.normal3f_bufferoffset = 0;
4842 case Q3DEFORM_NORMAL:
4843 // deform the normals to make reflections wavey
4844 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4846 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4847 for (j = 0;j < surface->num_vertices;j++)
4850 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4851 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4852 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4853 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
4854 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
4855 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
4856 VectorNormalize(normal);
4858 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);
4860 rsurface.svector3f = rsurface.array_deformedsvector3f;
4861 rsurface.svector3f_bufferobject = 0;
4862 rsurface.svector3f_bufferoffset = 0;
4863 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4864 rsurface.tvector3f_bufferobject = 0;
4865 rsurface.tvector3f_bufferoffset = 0;
4866 rsurface.normal3f = rsurface.array_deformednormal3f;
4867 rsurface.normal3f_bufferobject = 0;
4868 rsurface.normal3f_bufferoffset = 0;
4871 // deform vertex array to make wavey water and flags and such
4872 waveparms[0] = deform->waveparms[0];
4873 waveparms[1] = deform->waveparms[1];
4874 waveparms[2] = deform->waveparms[2];
4875 waveparms[3] = deform->waveparms[3];
4876 // this is how a divisor of vertex influence on deformation
4877 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4878 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4879 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4881 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4882 for (j = 0;j < surface->num_vertices;j++)
4884 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4885 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4886 // if the wavefunc depends on time, evaluate it per-vertex
4889 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4890 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4892 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4895 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4896 rsurface.vertex3f_bufferobject = 0;
4897 rsurface.vertex3f_bufferoffset = 0;
4899 case Q3DEFORM_BULGE:
4900 // deform vertex array to make the surface have moving bulges
4901 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4903 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4904 for (j = 0;j < surface->num_vertices;j++)
4906 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
4907 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4910 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4911 rsurface.vertex3f_bufferobject = 0;
4912 rsurface.vertex3f_bufferoffset = 0;
4915 // deform vertex array
4916 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4917 VectorScale(deform->parms, scale, waveparms);
4918 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4920 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4921 for (j = 0;j < surface->num_vertices;j++)
4922 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4924 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4925 rsurface.vertex3f_bufferobject = 0;
4926 rsurface.vertex3f_bufferoffset = 0;
4930 // generate texcoords based on the chosen texcoord source
4931 switch(rsurface.texture->tcgen.tcgen)
4934 case Q3TCGEN_TEXTURE:
4935 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4936 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4937 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4939 case Q3TCGEN_LIGHTMAP:
4940 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4941 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4942 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4944 case Q3TCGEN_VECTOR:
4945 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4947 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4948 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)
4950 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4951 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4954 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4955 rsurface.texcoordtexture2f_bufferobject = 0;
4956 rsurface.texcoordtexture2f_bufferoffset = 0;
4958 case Q3TCGEN_ENVIRONMENT:
4959 // make environment reflections using a spheremap
4960 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4962 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4963 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4964 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4965 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4966 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4968 float l, d, eyedir[3];
4969 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4970 l = 0.5f / VectorLength(eyedir);
4971 d = DotProduct(normal, eyedir)*2;
4972 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4973 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4976 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4977 rsurface.texcoordtexture2f_bufferobject = 0;
4978 rsurface.texcoordtexture2f_bufferoffset = 0;
4981 // the only tcmod that needs software vertex processing is turbulent, so
4982 // check for it here and apply the changes if needed
4983 // and we only support that as the first one
4984 // (handling a mixture of turbulent and other tcmods would be problematic
4985 // without punting it entirely to a software path)
4986 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4988 amplitude = rsurface.texture->tcmods[0].parms[1];
4989 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
4990 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4992 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4993 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)
4995 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4996 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4999 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5000 rsurface.texcoordtexture2f_bufferobject = 0;
5001 rsurface.texcoordtexture2f_bufferoffset = 0;
5003 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5004 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5005 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5006 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5009 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5012 const msurface_t *surface = texturesurfacelist[0];
5013 const msurface_t *surface2;
5018 // TODO: lock all array ranges before render, rather than on each surface
5019 if (texturenumsurfaces == 1)
5021 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5022 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));
5024 else if (r_batchmode.integer == 2)
5026 #define MAXBATCHTRIANGLES 4096
5027 int batchtriangles = 0;
5028 int batchelements[MAXBATCHTRIANGLES*3];
5029 for (i = 0;i < texturenumsurfaces;i = j)
5031 surface = texturesurfacelist[i];
5033 if (surface->num_triangles > MAXBATCHTRIANGLES)
5035 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));
5038 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5039 batchtriangles = surface->num_triangles;
5040 firstvertex = surface->num_firstvertex;
5041 endvertex = surface->num_firstvertex + surface->num_vertices;
5042 for (;j < texturenumsurfaces;j++)
5044 surface2 = texturesurfacelist[j];
5045 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5047 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5048 batchtriangles += surface2->num_triangles;
5049 firstvertex = min(firstvertex, surface2->num_firstvertex);
5050 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5052 surface2 = texturesurfacelist[j-1];
5053 numvertices = endvertex - firstvertex;
5054 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5057 else if (r_batchmode.integer == 1)
5059 for (i = 0;i < texturenumsurfaces;i = j)
5061 surface = texturesurfacelist[i];
5062 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5063 if (texturesurfacelist[j] != surface2)
5065 surface2 = texturesurfacelist[j-1];
5066 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5067 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5068 GL_LockArrays(surface->num_firstvertex, numvertices);
5069 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5074 for (i = 0;i < texturenumsurfaces;i++)
5076 surface = texturesurfacelist[i];
5077 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5078 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));
5083 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5085 int i, planeindex, vertexindex;
5089 r_waterstate_waterplane_t *p, *bestp;
5090 msurface_t *surface;
5091 if (r_waterstate.renderingscene)
5093 for (i = 0;i < texturenumsurfaces;i++)
5095 surface = texturesurfacelist[i];
5096 if (lightmaptexunit >= 0)
5097 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5098 if (deluxemaptexunit >= 0)
5099 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5100 // pick the closest matching water plane
5103 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5106 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5108 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5109 d += fabs(PlaneDiff(vert, &p->plane));
5111 if (bestd > d || !bestp)
5119 if (refractiontexunit >= 0)
5120 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5121 if (reflectiontexunit >= 0)
5122 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5126 if (refractiontexunit >= 0)
5127 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5128 if (reflectiontexunit >= 0)
5129 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5131 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5132 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));
5136 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5140 const msurface_t *surface = texturesurfacelist[0];
5141 const msurface_t *surface2;
5146 // TODO: lock all array ranges before render, rather than on each surface
5147 if (texturenumsurfaces == 1)
5149 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5150 if (deluxemaptexunit >= 0)
5151 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5152 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5153 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));
5155 else if (r_batchmode.integer == 2)
5157 #define MAXBATCHTRIANGLES 4096
5158 int batchtriangles = 0;
5159 int batchelements[MAXBATCHTRIANGLES*3];
5160 for (i = 0;i < texturenumsurfaces;i = j)
5162 surface = texturesurfacelist[i];
5163 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5164 if (deluxemaptexunit >= 0)
5165 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5167 if (surface->num_triangles > MAXBATCHTRIANGLES)
5169 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));
5172 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5173 batchtriangles = surface->num_triangles;
5174 firstvertex = surface->num_firstvertex;
5175 endvertex = surface->num_firstvertex + surface->num_vertices;
5176 for (;j < texturenumsurfaces;j++)
5178 surface2 = texturesurfacelist[j];
5179 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5181 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5182 batchtriangles += surface2->num_triangles;
5183 firstvertex = min(firstvertex, surface2->num_firstvertex);
5184 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5186 surface2 = texturesurfacelist[j-1];
5187 numvertices = endvertex - firstvertex;
5188 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5191 else if (r_batchmode.integer == 1)
5194 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5195 for (i = 0;i < texturenumsurfaces;i = j)
5197 surface = texturesurfacelist[i];
5198 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5199 if (texturesurfacelist[j] != surface2)
5201 Con_Printf(" %i", j - i);
5204 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5206 for (i = 0;i < texturenumsurfaces;i = j)
5208 surface = texturesurfacelist[i];
5209 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5210 if (deluxemaptexunit >= 0)
5211 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5212 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5213 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5216 Con_Printf(" %i", j - i);
5218 surface2 = texturesurfacelist[j-1];
5219 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5220 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5221 GL_LockArrays(surface->num_firstvertex, numvertices);
5222 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5230 for (i = 0;i < texturenumsurfaces;i++)
5232 surface = texturesurfacelist[i];
5233 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5234 if (deluxemaptexunit >= 0)
5235 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5236 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5237 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));
5242 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5245 int texturesurfaceindex;
5246 if (r_showsurfaces.integer == 2)
5248 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5250 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5251 for (j = 0;j < surface->num_triangles;j++)
5253 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5254 GL_Color(f, f, f, 1);
5255 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)));
5261 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5263 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5264 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5265 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);
5266 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5267 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));
5272 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5274 int texturesurfaceindex;
5278 if (rsurface.lightmapcolor4f)
5280 // generate color arrays for the surfaces in this list
5281 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5283 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5284 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)
5286 f = FogPoint_Model(v);
5296 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5298 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5299 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)
5301 f = FogPoint_Model(v);
5309 rsurface.lightmapcolor4f = rsurface.array_color4f;
5310 rsurface.lightmapcolor4f_bufferobject = 0;
5311 rsurface.lightmapcolor4f_bufferoffset = 0;
5314 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5316 int texturesurfaceindex;
5319 if (!rsurface.lightmapcolor4f)
5321 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5323 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5324 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)
5332 rsurface.lightmapcolor4f = rsurface.array_color4f;
5333 rsurface.lightmapcolor4f_bufferobject = 0;
5334 rsurface.lightmapcolor4f_bufferoffset = 0;
5337 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5340 rsurface.lightmapcolor4f = NULL;
5341 rsurface.lightmapcolor4f_bufferobject = 0;
5342 rsurface.lightmapcolor4f_bufferoffset = 0;
5343 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5344 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5345 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5346 GL_Color(r, g, b, a);
5347 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5350 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5352 // TODO: optimize applyfog && applycolor case
5353 // just apply fog if necessary, and tint the fog color array if necessary
5354 rsurface.lightmapcolor4f = NULL;
5355 rsurface.lightmapcolor4f_bufferobject = 0;
5356 rsurface.lightmapcolor4f_bufferoffset = 0;
5357 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5358 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5359 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5360 GL_Color(r, g, b, a);
5361 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5364 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5366 int texturesurfaceindex;
5370 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5372 // generate color arrays for the surfaces in this list
5373 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5375 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5376 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5378 if (surface->lightmapinfo->samples)
5380 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5381 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5382 VectorScale(lm, scale, c);
5383 if (surface->lightmapinfo->styles[1] != 255)
5385 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5387 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5388 VectorMA(c, scale, lm, c);
5389 if (surface->lightmapinfo->styles[2] != 255)
5392 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5393 VectorMA(c, scale, lm, c);
5394 if (surface->lightmapinfo->styles[3] != 255)
5397 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5398 VectorMA(c, scale, lm, c);
5408 rsurface.lightmapcolor4f = rsurface.array_color4f;
5409 rsurface.lightmapcolor4f_bufferobject = 0;
5410 rsurface.lightmapcolor4f_bufferoffset = 0;
5414 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5415 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5416 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5418 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5419 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5420 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5421 GL_Color(r, g, b, a);
5422 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5425 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5427 int texturesurfaceindex;
5431 vec3_t ambientcolor;
5432 vec3_t diffusecolor;
5436 VectorCopy(rsurface.modellight_lightdir, lightdir);
5437 f = 0.5f * r_refdef.lightmapintensity;
5438 ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5439 ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5440 ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5441 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5442 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5443 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5444 if (VectorLength2(diffusecolor) > 0)
5446 // generate color arrays for the surfaces in this list
5447 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5449 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5450 int numverts = surface->num_vertices;
5451 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5452 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5453 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5454 // q3-style directional shading
5455 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5457 if ((f = DotProduct(c2, lightdir)) > 0)
5458 VectorMA(ambientcolor, f, diffusecolor, c);
5460 VectorCopy(ambientcolor, c);
5469 rsurface.lightmapcolor4f = rsurface.array_color4f;
5470 rsurface.lightmapcolor4f_bufferobject = 0;
5471 rsurface.lightmapcolor4f_bufferoffset = 0;
5475 r = ambientcolor[0];
5476 g = ambientcolor[1];
5477 b = ambientcolor[2];
5478 rsurface.lightmapcolor4f = NULL;
5479 rsurface.lightmapcolor4f_bufferobject = 0;
5480 rsurface.lightmapcolor4f_bufferoffset = 0;
5482 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5483 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5484 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5485 GL_Color(r, g, b, a);
5486 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5489 void RSurf_SetupDepthAndCulling(void)
5491 // submodels are biased to avoid z-fighting with world surfaces that they
5492 // may be exactly overlapping (avoids z-fighting artifacts on certain
5493 // doors and things in Quake maps)
5494 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5495 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5496 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5497 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
5500 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5502 RSurf_SetupDepthAndCulling();
5503 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5505 rsurface.mode = RSURFMODE_SHOWSURFACES;
5507 GL_BlendFunc(GL_ONE, GL_ZERO);
5508 R_Mesh_ColorPointer(NULL, 0, 0);
5509 R_Mesh_ResetTextureState();
5511 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5512 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5515 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5517 // transparent sky would be ridiculous
5518 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5520 if (rsurface.mode != RSURFMODE_SKY)
5522 if (rsurface.mode == RSURFMODE_GLSL)
5524 qglUseProgramObjectARB(0);CHECKGLERROR
5526 rsurface.mode = RSURFMODE_SKY;
5530 skyrendernow = false;
5532 // restore entity matrix
5533 R_Mesh_Matrix(&rsurface.matrix);
5535 RSurf_SetupDepthAndCulling();
5537 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5538 // skymasking on them, and Quake3 never did sky masking (unlike
5539 // software Quake and software Quake2), so disable the sky masking
5540 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5541 // and skymasking also looks very bad when noclipping outside the
5542 // level, so don't use it then either.
5543 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
5545 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5546 R_Mesh_ColorPointer(NULL, 0, 0);
5547 R_Mesh_ResetTextureState();
5548 if (skyrendermasked)
5550 // depth-only (masking)
5551 GL_ColorMask(0,0,0,0);
5552 // just to make sure that braindead drivers don't draw
5553 // anything despite that colormask...
5554 GL_BlendFunc(GL_ZERO, GL_ONE);
5559 GL_BlendFunc(GL_ONE, GL_ZERO);
5561 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5562 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5563 if (skyrendermasked)
5564 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5568 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5570 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5573 if (rsurface.mode != RSURFMODE_GLSL)
5575 rsurface.mode = RSURFMODE_GLSL;
5576 R_Mesh_ResetTextureState();
5577 GL_Color(1, 1, 1, 1);
5580 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5581 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5582 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5583 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5584 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5585 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5586 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5587 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5589 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5590 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5591 R_Mesh_ColorPointer(NULL, 0, 0);
5593 else if (rsurface.uselightmaptexture)
5595 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5596 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5597 R_Mesh_ColorPointer(NULL, 0, 0);
5601 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5602 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5603 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5605 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5606 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5607 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5609 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5611 // render background
5612 GL_BlendFunc(GL_ONE, GL_ZERO);
5614 GL_AlphaTest(false);
5616 GL_Color(1, 1, 1, 1);
5617 R_Mesh_ColorPointer(NULL, 0, 0);
5619 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5620 if (r_glsl_permutation)
5622 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5623 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5624 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5625 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5626 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5627 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5628 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5631 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5632 GL_DepthMask(false);
5633 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5634 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5636 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5637 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5638 R_Mesh_ColorPointer(NULL, 0, 0);
5640 else if (rsurface.uselightmaptexture)
5642 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5643 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5644 R_Mesh_ColorPointer(NULL, 0, 0);
5648 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5649 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5650 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5652 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5653 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5656 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5657 if (!r_glsl_permutation)
5660 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5661 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5662 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5663 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5664 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5665 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5667 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5669 GL_BlendFunc(GL_ONE, GL_ZERO);
5671 GL_AlphaTest(false);
5674 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5676 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5677 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);
5679 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5683 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5684 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);
5686 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5688 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5693 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5695 // OpenGL 1.3 path - anything not completely ancient
5696 int texturesurfaceindex;
5697 qboolean applycolor;
5701 const texturelayer_t *layer;
5702 if (rsurface.mode != RSURFMODE_MULTIPASS)
5703 rsurface.mode = RSURFMODE_MULTIPASS;
5704 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5706 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5709 int layertexrgbscale;
5710 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5712 if (layerindex == 0)
5716 GL_AlphaTest(false);
5717 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5720 GL_DepthMask(layer->depthmask);
5721 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5722 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
5724 layertexrgbscale = 4;
5725 VectorScale(layer->color, 0.25f, layercolor);
5727 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
5729 layertexrgbscale = 2;
5730 VectorScale(layer->color, 0.5f, layercolor);
5734 layertexrgbscale = 1;
5735 VectorScale(layer->color, 1.0f, layercolor);
5737 layercolor[3] = layer->color[3];
5738 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5739 R_Mesh_ColorPointer(NULL, 0, 0);
5740 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5741 switch (layer->type)
5743 case TEXTURELAYERTYPE_LITTEXTURE:
5744 memset(&m, 0, sizeof(m));
5745 m.tex[0] = R_GetTexture(r_texture_white);
5746 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5747 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5748 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5749 m.tex[1] = R_GetTexture(layer->texture);
5750 m.texmatrix[1] = layer->texmatrix;
5751 m.texrgbscale[1] = layertexrgbscale;
5752 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5753 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5754 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5755 R_Mesh_TextureState(&m);
5756 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5757 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5758 else if (rsurface.uselightmaptexture)
5759 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5761 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5763 case TEXTURELAYERTYPE_TEXTURE:
5764 memset(&m, 0, sizeof(m));
5765 m.tex[0] = R_GetTexture(layer->texture);
5766 m.texmatrix[0] = layer->texmatrix;
5767 m.texrgbscale[0] = layertexrgbscale;
5768 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5769 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5770 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5771 R_Mesh_TextureState(&m);
5772 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5774 case TEXTURELAYERTYPE_FOG:
5775 memset(&m, 0, sizeof(m));
5776 m.texrgbscale[0] = layertexrgbscale;
5779 m.tex[0] = R_GetTexture(layer->texture);
5780 m.texmatrix[0] = layer->texmatrix;
5781 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5782 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5783 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5785 R_Mesh_TextureState(&m);
5786 // generate a color array for the fog pass
5787 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5788 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5792 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5793 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)
5795 f = 1 - FogPoint_Model(v);
5796 c[0] = layercolor[0];
5797 c[1] = layercolor[1];
5798 c[2] = layercolor[2];
5799 c[3] = f * layercolor[3];
5802 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5805 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5807 GL_LockArrays(0, 0);
5810 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5812 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5813 GL_AlphaTest(false);
5817 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5819 // OpenGL 1.1 - crusty old voodoo path
5820 int texturesurfaceindex;
5824 const texturelayer_t *layer;
5825 if (rsurface.mode != RSURFMODE_MULTIPASS)
5826 rsurface.mode = RSURFMODE_MULTIPASS;
5827 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5829 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5831 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5833 if (layerindex == 0)
5837 GL_AlphaTest(false);
5838 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5841 GL_DepthMask(layer->depthmask);
5842 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5843 R_Mesh_ColorPointer(NULL, 0, 0);
5844 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5845 switch (layer->type)
5847 case TEXTURELAYERTYPE_LITTEXTURE:
5848 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5850 // two-pass lit texture with 2x rgbscale
5851 // first the lightmap pass
5852 memset(&m, 0, sizeof(m));
5853 m.tex[0] = R_GetTexture(r_texture_white);
5854 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5855 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5856 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5857 R_Mesh_TextureState(&m);
5858 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5859 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5860 else if (rsurface.uselightmaptexture)
5861 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5863 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5864 GL_LockArrays(0, 0);
5865 // then apply the texture to it
5866 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5867 memset(&m, 0, sizeof(m));
5868 m.tex[0] = R_GetTexture(layer->texture);
5869 m.texmatrix[0] = layer->texmatrix;
5870 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5871 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5872 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5873 R_Mesh_TextureState(&m);
5874 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);
5878 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5879 memset(&m, 0, sizeof(m));
5880 m.tex[0] = R_GetTexture(layer->texture);
5881 m.texmatrix[0] = layer->texmatrix;
5882 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5883 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5884 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5885 R_Mesh_TextureState(&m);
5886 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5887 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);
5889 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);
5892 case TEXTURELAYERTYPE_TEXTURE:
5893 // singletexture unlit texture with transparency support
5894 memset(&m, 0, sizeof(m));
5895 m.tex[0] = R_GetTexture(layer->texture);
5896 m.texmatrix[0] = layer->texmatrix;
5897 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5898 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5899 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5900 R_Mesh_TextureState(&m);
5901 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);
5903 case TEXTURELAYERTYPE_FOG:
5904 // singletexture fogging
5905 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5908 memset(&m, 0, sizeof(m));
5909 m.tex[0] = R_GetTexture(layer->texture);
5910 m.texmatrix[0] = layer->texmatrix;
5911 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5912 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5913 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5914 R_Mesh_TextureState(&m);
5917 R_Mesh_ResetTextureState();
5918 // generate a color array for the fog pass
5919 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5923 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5924 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)
5926 f = 1 - FogPoint_Model(v);
5927 c[0] = layer->color[0];
5928 c[1] = layer->color[1];
5929 c[2] = layer->color[2];
5930 c[3] = f * layer->color[3];
5933 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5936 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5938 GL_LockArrays(0, 0);
5941 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5943 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5944 GL_AlphaTest(false);
5948 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5950 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5952 rsurface.rtlight = NULL;
5956 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5958 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5960 if (rsurface.mode != RSURFMODE_MULTIPASS)
5961 rsurface.mode = RSURFMODE_MULTIPASS;
5962 if (r_depthfirst.integer == 3)
5964 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5965 if (!r_refdef.view.showdebug)
5966 GL_Color(0, 0, 0, 1);
5968 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5972 GL_ColorMask(0,0,0,0);
5975 RSurf_SetupDepthAndCulling();
5977 GL_BlendFunc(GL_ONE, GL_ZERO);
5979 GL_AlphaTest(false);
5980 R_Mesh_ColorPointer(NULL, 0, 0);
5981 R_Mesh_ResetTextureState();
5982 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5983 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5984 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5986 else if (r_depthfirst.integer == 3)
5988 else if (!r_refdef.view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5990 GL_Color(0, 0, 0, 1);
5991 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5993 else if (r_showsurfaces.integer)
5995 if (rsurface.mode != RSURFMODE_MULTIPASS)
5996 rsurface.mode = RSURFMODE_MULTIPASS;
5997 RSurf_SetupDepthAndCulling();
5999 GL_BlendFunc(GL_ONE, GL_ZERO);
6000 GL_DepthMask(writedepth);
6002 GL_AlphaTest(false);
6003 R_Mesh_ColorPointer(NULL, 0, 0);
6004 R_Mesh_ResetTextureState();
6005 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6006 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6008 else if (gl_lightmaps.integer)
6011 if (rsurface.mode != RSURFMODE_MULTIPASS)
6012 rsurface.mode = RSURFMODE_MULTIPASS;
6013 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6015 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6016 GL_BlendFunc(GL_ONE, GL_ZERO);
6017 GL_DepthMask(writedepth);
6019 GL_AlphaTest(false);
6020 R_Mesh_ColorPointer(NULL, 0, 0);
6021 memset(&m, 0, sizeof(m));
6022 m.tex[0] = R_GetTexture(r_texture_white);
6023 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6024 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6025 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6026 R_Mesh_TextureState(&m);
6027 RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist);
6028 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6029 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6030 else if (rsurface.uselightmaptexture)
6031 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6033 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6035 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6036 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6037 else if (rsurface.texture->currentnumlayers)
6039 // write depth for anything we skipped on the depth-only pass earlier
6040 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6042 RSurf_SetupDepthAndCulling();
6043 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6044 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6045 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6046 if (r_glsl.integer && gl_support_fragment_shader)
6047 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
6048 else if (gl_combine.integer && r_textureunits.integer >= 2)
6049 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
6051 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
6054 GL_LockArrays(0, 0);
6057 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6060 int texturenumsurfaces, endsurface;
6062 msurface_t *surface;
6063 msurface_t *texturesurfacelist[1024];
6065 // if the model is static it doesn't matter what value we give for
6066 // wantnormals and wanttangents, so this logic uses only rules applicable
6067 // to a model, knowing that they are meaningless otherwise
6068 if (ent == r_refdef.scene.worldentity)
6069 RSurf_ActiveWorldEntity();
6070 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6071 RSurf_ActiveModelEntity(ent, false, false);
6073 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6075 for (i = 0;i < numsurfaces;i = j)
6078 surface = rsurface.modelsurfaces + surfacelist[i];
6079 texture = surface->texture;
6080 R_UpdateTextureInfo(ent, texture);
6081 rsurface.texture = texture->currentframe;
6082 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6083 // scan ahead until we find a different texture
6084 endsurface = min(i + 1024, numsurfaces);
6085 texturenumsurfaces = 0;
6086 texturesurfacelist[texturenumsurfaces++] = surface;
6087 for (;j < endsurface;j++)
6089 surface = rsurface.modelsurfaces + surfacelist[j];
6090 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6092 texturesurfacelist[texturenumsurfaces++] = surface;
6094 // render the range of surfaces
6095 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
6101 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6104 vec3_t tempcenter, center;
6106 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6109 for (i = 0;i < numsurfaces;i++)
6110 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6111 R_Water_AddWaterPlane(surfacelist[i]);
6114 // break the surface list down into batches by texture and use of lightmapping
6115 for (i = 0;i < numsurfaces;i = j)
6118 // texture is the base texture pointer, rsurface.texture is the
6119 // current frame/skin the texture is directing us to use (for example
6120 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6121 // use skin 1 instead)
6122 texture = surfacelist[i]->texture;
6123 rsurface.texture = texture->currentframe;
6124 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6125 if (!(rsurface.texture->currentmaterialflags & flagsmask))
6127 // if this texture is not the kind we want, skip ahead to the next one
6128 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6132 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6134 // transparent surfaces get pushed off into the transparent queue
6135 const msurface_t *surface = surfacelist[i];
6138 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6139 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6140 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6141 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6142 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
6146 // simply scan ahead until we find a different texture or lightmap state
6147 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6149 // render the range of surfaces
6150 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6155 float locboxvertex3f[6*4*3] =
6157 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6158 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6159 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6160 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6161 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6162 1,0,0, 0,0,0, 0,1,0, 1,1,0
6165 int locboxelement3i[6*2*3] =
6175 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6178 cl_locnode_t *loc = (cl_locnode_t *)ent;
6180 float vertex3f[6*4*3];
6182 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6183 GL_DepthMask(false);
6184 GL_DepthRange(0, 1);
6185 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6187 GL_CullFace(GL_NONE);
6188 R_Mesh_Matrix(&identitymatrix);
6190 R_Mesh_VertexPointer(vertex3f, 0, 0);
6191 R_Mesh_ColorPointer(NULL, 0, 0);
6192 R_Mesh_ResetTextureState();
6195 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6196 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6197 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6198 surfacelist[0] < 0 ? 0.5f : 0.125f);
6200 if (VectorCompare(loc->mins, loc->maxs))
6202 VectorSet(size, 2, 2, 2);
6203 VectorMA(loc->mins, -0.5f, size, mins);
6207 VectorCopy(loc->mins, mins);
6208 VectorSubtract(loc->maxs, loc->mins, size);
6211 for (i = 0;i < 6*4*3;)
6212 for (j = 0;j < 3;j++, i++)
6213 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6215 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6218 void R_DrawLocs(void)
6221 cl_locnode_t *loc, *nearestloc;
6223 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6224 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6226 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6227 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6231 void R_DrawDebugModel(entity_render_t *ent)
6233 int i, j, k, l, flagsmask;
6234 const int *elements;
6236 msurface_t *surface;
6237 model_t *model = ent->model;
6240 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6242 R_Mesh_ColorPointer(NULL, 0, 0);
6243 R_Mesh_ResetTextureState();
6244 GL_DepthRange(0, 1);
6245 GL_DepthTest(!r_showdisabledepthtest.integer);
6246 GL_DepthMask(false);
6247 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6249 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6251 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6252 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6254 if (brush->colbrushf && brush->colbrushf->numtriangles)
6256 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6257 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);
6258 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6261 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6263 if (surface->num_collisiontriangles)
6265 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6266 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);
6267 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6272 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6274 if (r_showtris.integer || r_shownormals.integer)
6276 if (r_showdisabledepthtest.integer)
6278 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6279 GL_DepthMask(false);
6283 GL_BlendFunc(GL_ONE, GL_ZERO);
6286 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6288 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
6290 rsurface.texture = surface->texture->currentframe;
6291 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6293 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6294 if (r_showtris.value > 0)
6296 if (!rsurface.texture->currentlayers->depthmask)
6297 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
6298 else if (ent == r_refdef.scene.worldentity)
6299 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
6301 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
6302 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6305 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6307 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6308 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6309 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6310 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6315 if (r_shownormals.value > 0)
6318 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6320 VectorCopy(rsurface.vertex3f + l * 3, v);
6321 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
6322 qglVertex3f(v[0], v[1], v[2]);
6323 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6324 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6325 qglVertex3f(v[0], v[1], v[2]);
6330 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6332 VectorCopy(rsurface.vertex3f + l * 3, v);
6333 GL_Color(0, r_refdef.view.colorscale, 0, 1);
6334 qglVertex3f(v[0], v[1], v[2]);
6335 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6336 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6337 qglVertex3f(v[0], v[1], v[2]);
6342 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6344 VectorCopy(rsurface.vertex3f + l * 3, v);
6345 GL_Color(0, 0, r_refdef.view.colorscale, 1);
6346 qglVertex3f(v[0], v[1], v[2]);
6347 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6348 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6349 qglVertex3f(v[0], v[1], v[2]);
6356 rsurface.texture = NULL;
6360 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6361 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6363 int i, j, endj, f, flagsmask;
6364 msurface_t *surface;
6366 model_t *model = r_refdef.scene.worldmodel;
6367 const int maxsurfacelist = 1024;
6368 int numsurfacelist = 0;
6369 msurface_t *surfacelist[1024];
6373 RSurf_ActiveWorldEntity();
6375 // update light styles on this submodel
6376 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6378 model_brush_lightstyleinfo_t *style;
6379 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6381 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6383 msurface_t *surfaces = model->data_surfaces;
6384 int *list = style->surfacelist;
6385 style->value = r_refdef.scene.lightstylevalue[style->style];
6386 for (j = 0;j < style->numsurfaces;j++)
6387 surfaces[list[j]].cached_dlight = true;
6392 R_UpdateAllTextureInfo(r_refdef.scene.worldentity);
6393 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6397 R_DrawDebugModel(r_refdef.scene.worldentity);
6403 rsurface.uselightmaptexture = false;
6404 rsurface.texture = NULL;
6406 j = model->firstmodelsurface;
6407 endj = j + model->nummodelsurfaces;
6410 // quickly skip over non-visible surfaces
6411 for (;j < endj && !r_refdef.viewcache.world_surfacevisible[j];j++)
6413 // quickly iterate over visible surfaces
6414 for (;j < endj && r_refdef.viewcache.world_surfacevisible[j];j++)
6416 // process this surface
6417 surface = model->data_surfaces + j;
6418 // if this surface fits the criteria, add it to the list
6419 if (surface->num_triangles)
6421 // if lightmap parameters changed, rebuild lightmap texture
6422 if (surface->cached_dlight)
6423 R_BuildLightMap(r_refdef.scene.worldentity, surface);
6424 // add face to draw list
6425 surfacelist[numsurfacelist++] = surface;
6426 r_refdef.stats.world_triangles += surface->num_triangles;
6427 if (numsurfacelist >= maxsurfacelist)
6429 r_refdef.stats.world_surfaces += numsurfacelist;
6430 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6436 r_refdef.stats.world_surfaces += numsurfacelist;
6438 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6442 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6444 int i, j, f, flagsmask;
6445 msurface_t *surface, *endsurface;
6447 model_t *model = ent->model;
6448 const int maxsurfacelist = 1024;
6449 int numsurfacelist = 0;
6450 msurface_t *surfacelist[1024];
6454 // if the model is static it doesn't matter what value we give for
6455 // wantnormals and wanttangents, so this logic uses only rules applicable
6456 // to a model, knowing that they are meaningless otherwise
6457 if (ent == r_refdef.scene.worldentity)
6458 RSurf_ActiveWorldEntity();
6459 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6460 RSurf_ActiveModelEntity(ent, false, false);
6462 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6464 // update light styles
6465 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6467 model_brush_lightstyleinfo_t *style;
6468 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6470 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6472 msurface_t *surfaces = model->data_surfaces;
6473 int *list = style->surfacelist;
6474 style->value = r_refdef.scene.lightstylevalue[style->style];
6475 for (j = 0;j < style->numsurfaces;j++)
6476 surfaces[list[j]].cached_dlight = true;
6481 R_UpdateAllTextureInfo(ent);
6482 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6486 R_DrawDebugModel(ent);
6492 rsurface.uselightmaptexture = false;
6493 rsurface.texture = NULL;
6495 surface = model->data_surfaces + model->firstmodelsurface;
6496 endsurface = surface + model->nummodelsurfaces;
6497 for (;surface < endsurface;surface++)
6499 // if this surface fits the criteria, add it to the list
6500 if (surface->num_triangles)
6502 // if lightmap parameters changed, rebuild lightmap texture
6503 if (surface->cached_dlight)
6504 R_BuildLightMap(ent, surface);
6505 // add face to draw list
6506 surfacelist[numsurfacelist++] = surface;
6507 r_refdef.stats.entities_triangles += surface->num_triangles;
6508 if (numsurfacelist >= maxsurfacelist)
6510 r_refdef.stats.entities_surfaces += numsurfacelist;
6511 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6516 r_refdef.stats.entities_surfaces += numsurfacelist;
6518 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);