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 myhvec2 hvec2\n"
459 "# define myhvec3 hvec3\n"
460 "# define myhvec4 hvec4\n"
462 "# define myhalf float\n"
463 "# define myhvec2 vec2\n"
464 "# define myhvec3 vec3\n"
465 "# define myhvec4 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 myhvec3 LightColor;\n"
608 "uniform myhvec3 AmbientColor;\n"
609 "uniform myhvec3 DiffuseColor;\n"
610 "uniform myhvec3 SpecularColor;\n"
611 "uniform myhvec3 Color_Pants;\n"
612 "uniform myhvec3 Color_Shirt;\n"
613 "uniform myhvec3 FogColor;\n"
615 "uniform myhvec4 TintColor;\n"
618 "//#ifdef MODE_WATER\n"
619 "uniform vec4 DistortScaleRefractReflect;\n"
620 "uniform vec4 ScreenScaleRefractReflect;\n"
621 "uniform vec4 ScreenCenterRefractReflect;\n"
622 "uniform myhvec4 RefractColor;\n"
623 "uniform myhvec4 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 myhvec4 RefractColor;\n"
632 "//# ifdef USEREFLECTION\n"
633 "//uniform myhvec4 ReflectColor;\n"
636 "//# ifdef USEREFLECTION\n"
637 "//uniform vec4 DistortScaleRefractReflect;\n"
638 "//uniform vec4 ScreenScaleRefractReflect;\n"
639 "//uniform vec4 ScreenCenterRefractReflect;\n"
640 "//uniform myhvec4 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(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
718 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(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(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
737 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(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 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
752 "#ifdef USECOLORMAPPING\n"
753 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(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 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
768 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
769 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(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)) * myhvec3(texture2D(Texture_Gloss, TexCoord)));\n"
774 "# ifdef USEDIFFUSE\n"
775 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
776 " myhvec3 diffusenormal = myhvec3(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 *= myhvec3(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 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
801 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
803 " // calculate directional shading\n"
804 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
805 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
806 " color.rgb += myhvec3(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 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
811 " myhvec3 diffusenormal = myhvec3(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 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
832 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
833 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
834 " // calculate directional shading\n"
835 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
836 "# ifdef USESPECULAR\n"
837 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
838 " tempcolor += myhvec3(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 * myhvec3(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 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
856 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
857 " // calculate directional shading\n"
858 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
859 "# ifdef USESPECULAR\n"
860 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
861 " tempcolor += myhvec3(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 * myhvec3(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 * myhvec3(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 * myhvec3(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 += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
908 "#ifdef USECONTRASTBOOST\n"
909 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhvec3(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, myhvec2(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(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
923 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
924 " color.rgb = mix(color.rgb, myhvec3(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 #define SHADERPERMUTATION_COLORMAPPING (1<<0) // indicates this is a colormapped skin
936 #define SHADERPERMUTATION_CONTRASTBOOST (1<<1) // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
937 #define SHADERPERMUTATION_FOG (1<<2) // tint the color by fog color or black if using additive blend mode
938 #define SHADERPERMUTATION_CUBEFILTER (1<<3) // (lightsource) use cubemap light filter
939 #define SHADERPERMUTATION_GLOW (1<<4) // (lightmap) blend in an additive glow texture
940 #define SHADERPERMUTATION_DIFFUSE (1<<5) // (lightsource) whether to use directional shading
941 #define SHADERPERMUTATION_SPECULAR (1<<6) // (lightsource or deluxemapping) render specular effects
942 #define SHADERPERMUTATION_REFLECTION (1<<7) // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
943 #define SHADERPERMUTATION_OFFSETMAPPING (1<<8) // adjust texcoords to roughly simulate a displacement mapped surface
944 #define SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING (1<<9) // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
945 #define SHADERPERMUTATION_MODEBASE (1<<10) // multiplier for the SHADERMODE_ values to get a valid index
947 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
948 const char *shaderpermutationinfo[][2] =
950 {"#define USECOLORMAPPING\n", " colormapping"},
951 {"#define USECONTRASTBOOST\n", " contrastboost"},
952 {"#define USEFOG\n", " fog"},
953 {"#define USECUBEFILTER\n", " cubefilter"},
954 {"#define USEGLOW\n", " glow"},
955 {"#define USEDIFFUSE\n", " diffuse"},
956 {"#define USESPECULAR\n", " specular"},
957 {"#define USEREFLECTION\n", " reflection"},
958 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
959 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
963 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
964 typedef enum shadermode_e
966 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
967 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
968 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
969 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
970 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
971 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
972 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
973 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
974 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
979 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
980 const char *shadermodeinfo[][2] =
982 {"#define MODE_FLATCOLOR\n", " flatcolor"},
983 {"#define MODE_VERTEXCOLOR\n", " vertexcolor"},
984 {"#define MODE_LIGHTMAP\n", " lightmap"},
985 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
986 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
987 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
988 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
989 {"#define MODE_REFRACTION\n", " refraction"},
990 {"#define MODE_WATER\n", " water"},
994 #define SHADERPERMUTATION_INDICES (SHADERPERMUTATION_MODEBASE * SHADERMODE_COUNT)
996 typedef struct r_glsl_permutation_s
998 // indicates if we have tried compiling this permutation already
1000 // 0 if compilation failed
1002 // locations of detected uniforms in program object, or -1 if not found
1003 int loc_Texture_Normal;
1004 int loc_Texture_Color;
1005 int loc_Texture_Gloss;
1006 int loc_Texture_Cube;
1007 int loc_Texture_Attenuation;
1008 int loc_Texture_FogMask;
1009 int loc_Texture_Pants;
1010 int loc_Texture_Shirt;
1011 int loc_Texture_Lightmap;
1012 int loc_Texture_Deluxemap;
1013 int loc_Texture_Glow;
1014 int loc_Texture_Refraction;
1015 int loc_Texture_Reflection;
1017 int loc_LightPosition;
1018 int loc_EyePosition;
1020 int loc_Color_Pants;
1021 int loc_Color_Shirt;
1022 int loc_FogRangeRecip;
1023 int loc_AmbientScale;
1024 int loc_DiffuseScale;
1025 int loc_SpecularScale;
1026 int loc_SpecularPower;
1028 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1029 int loc_OffsetMapping_Scale;
1031 int loc_AmbientColor;
1032 int loc_DiffuseColor;
1033 int loc_SpecularColor;
1035 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1036 int loc_DistortScaleRefractReflect;
1037 int loc_ScreenScaleRefractReflect;
1038 int loc_ScreenCenterRefractReflect;
1039 int loc_RefractColor;
1040 int loc_ReflectColor;
1041 int loc_ReflectFactor;
1042 int loc_ReflectOffset;
1044 r_glsl_permutation_t;
1046 // information about each possible shader permutation
1047 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_INDICES];
1048 // currently selected permutation
1049 r_glsl_permutation_t *r_glsl_permutation;
1051 // these are additional flags used only by R_GLSL_CompilePermutation
1052 #define SHADERTYPE_USES_VERTEXSHADER (1<<0)
1053 #define SHADERTYPE_USES_GEOMETRYSHADER (1<<1)
1054 #define SHADERTYPE_USES_FRAGMENTSHADER (1<<2)
1056 static void R_GLSL_CompilePermutation(const char *filename, int permutation, int shadertype)
1059 qboolean shaderfound;
1060 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
1061 int vertstrings_count;
1062 int geomstrings_count;
1063 int fragstrings_count;
1065 const char *vertstrings_list[32+1];
1066 const char *geomstrings_list[32+1];
1067 const char *fragstrings_list[32+1];
1068 char permutationname[256];
1073 vertstrings_list[0] = "#define VERTEX_SHADER\n";
1074 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
1075 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
1076 vertstrings_count = 1;
1077 geomstrings_count = 1;
1078 fragstrings_count = 1;
1079 permutationname[0] = 0;
1080 i = permutation / SHADERPERMUTATION_MODEBASE;
1081 vertstrings_list[vertstrings_count++] = shadermodeinfo[i][0];
1082 geomstrings_list[geomstrings_count++] = shadermodeinfo[i][0];
1083 fragstrings_list[fragstrings_count++] = shadermodeinfo[i][0];
1084 strlcat(permutationname, shadermodeinfo[i][1], sizeof(permutationname));
1085 for (i = 0;shaderpermutationinfo[i][0];i++)
1087 if (permutation & (1<<i))
1089 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i][0];
1090 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i][0];
1091 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i][0];
1092 strlcat(permutationname, shaderpermutationinfo[i][1], sizeof(permutationname));
1096 // keep line numbers correct
1097 vertstrings_list[vertstrings_count++] = "\n";
1098 geomstrings_list[geomstrings_count++] = "\n";
1099 fragstrings_list[fragstrings_count++] = "\n";
1102 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1103 shaderfound = false;
1106 Con_DPrint("from disk... ");
1107 vertstrings_list[vertstrings_count++] = shaderstring;
1108 geomstrings_list[geomstrings_count++] = shaderstring;
1109 fragstrings_list[fragstrings_count++] = shaderstring;
1112 else if (!strcmp(filename, "glsl/default.glsl"))
1114 vertstrings_list[vertstrings_count++] = builtinshaderstring;
1115 geomstrings_list[geomstrings_count++] = builtinshaderstring;
1116 fragstrings_list[fragstrings_count++] = builtinshaderstring;
1119 // clear any lists that are not needed by this shader
1120 if (!(shadertype & SHADERTYPE_USES_VERTEXSHADER))
1121 vertstrings_count = 0;
1122 if (!(shadertype & SHADERTYPE_USES_GEOMETRYSHADER))
1123 geomstrings_count = 0;
1124 if (!(shadertype & SHADERTYPE_USES_FRAGMENTSHADER))
1125 fragstrings_count = 0;
1126 // compile the shader program
1127 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
1128 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1132 qglUseProgramObjectARB(p->program);CHECKGLERROR
1133 // look up all the uniform variable names we care about, so we don't
1134 // have to look them up every time we set them
1135 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1136 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1137 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1138 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1139 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1140 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1141 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1142 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1143 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1144 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1145 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1146 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1147 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1148 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1149 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1150 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1151 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
1152 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1153 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1154 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1155 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1156 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1157 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1158 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1159 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1160 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1161 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1162 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1163 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1164 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1165 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1166 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1167 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1168 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1169 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1170 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1171 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1172 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1173 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1174 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1175 // initialize the samplers to refer to the texture units we use
1176 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
1177 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
1178 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
1179 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
1180 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
1181 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
1182 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
1183 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
1184 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
1185 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
1186 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
1187 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
1188 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
1190 qglUseProgramObjectARB(0);CHECKGLERROR
1191 if (developer.integer)
1192 Con_Printf("GLSL shader %s :%s compiled.\n", filename, permutationname);
1196 if (developer.integer)
1197 Con_Printf("GLSL shader %s :%s failed! source code line offset for above errors is %i.\n", permutationname, filename, -(vertstrings_count - 1));
1199 Con_Printf("GLSL shader %s :%s failed! some features may not work properly.\n", permutationname, filename);
1202 Mem_Free(shaderstring);
1205 void R_GLSL_Restart_f(void)
1208 for (i = 0;i < SHADERPERMUTATION_INDICES;i++)
1209 if (r_glsl_permutations[i].program)
1210 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
1211 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1214 void R_GLSL_DumpShader_f(void)
1218 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1221 Con_Printf("failed to write to glsl/default.glsl\n");
1225 FS_Print(file, "// The engine may define the following macros:\n");
1226 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1227 for (i = 0;shadermodeinfo[i][0];i++)
1228 FS_Printf(file, "// %s", shadermodeinfo[i][0]);
1229 for (i = 0;shaderpermutationinfo[i][0];i++)
1230 FS_Printf(file, "// %s", shaderpermutationinfo[i][0]);
1231 FS_Print(file, "\n");
1232 FS_Print(file, builtinshaderstring);
1235 Con_Printf("glsl/default.glsl written\n");
1238 extern rtexture_t *r_shadow_attenuationgradienttexture;
1239 extern rtexture_t *r_shadow_attenuation2dtexture;
1240 extern rtexture_t *r_shadow_attenuation3dtexture;
1241 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1243 // select a permutation of the lighting shader appropriate to this
1244 // combination of texture, entity, light source, and fogging, only use the
1245 // minimum features necessary to avoid wasting rendering time in the
1246 // fragment shader on features that are not being used
1247 const char *shaderfilename = NULL;
1248 unsigned int permutation = 0;
1249 unsigned int shadertype = 0;
1250 shadermode_t mode = 0;
1251 r_glsl_permutation = NULL;
1252 shaderfilename = "glsl/default.glsl";
1253 shadertype = SHADERTYPE_USES_VERTEXSHADER | SHADERTYPE_USES_FRAGMENTSHADER;
1254 // TODO: implement geometry-shader based shadow volumes someday
1255 if (r_glsl_offsetmapping.integer)
1257 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1258 if (r_glsl_offsetmapping_reliefmapping.integer)
1259 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1261 if (rsurfacepass == RSURFPASS_BACKGROUND)
1263 // distorted background
1264 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1265 mode = SHADERMODE_WATER;
1267 mode = SHADERMODE_REFRACTION;
1269 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1272 mode = SHADERMODE_LIGHTSOURCE;
1273 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1274 permutation |= SHADERPERMUTATION_CUBEFILTER;
1275 if (diffusescale > 0)
1276 permutation |= SHADERPERMUTATION_DIFFUSE;
1277 if (specularscale > 0)
1278 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1279 if (r_refdef.fogenabled)
1280 permutation |= SHADERPERMUTATION_FOG;
1281 if (rsurface.texture->colormapping)
1282 permutation |= SHADERPERMUTATION_COLORMAPPING;
1283 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1284 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1286 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1288 // unshaded geometry (fullbright or ambient model lighting)
1289 mode = SHADERMODE_FLATCOLOR;
1290 if (rsurface.texture->currentskinframe->glow)
1291 permutation |= SHADERPERMUTATION_GLOW;
1292 if (r_refdef.fogenabled)
1293 permutation |= SHADERPERMUTATION_FOG;
1294 if (rsurface.texture->colormapping)
1295 permutation |= SHADERPERMUTATION_COLORMAPPING;
1296 if (r_glsl_offsetmapping.integer)
1298 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1299 if (r_glsl_offsetmapping_reliefmapping.integer)
1300 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1302 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1303 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1304 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1305 permutation |= SHADERPERMUTATION_REFLECTION;
1307 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1309 // directional model lighting
1310 mode = SHADERMODE_LIGHTDIRECTION;
1311 if (rsurface.texture->currentskinframe->glow)
1312 permutation |= SHADERPERMUTATION_GLOW;
1313 permutation |= SHADERPERMUTATION_DIFFUSE;
1314 if (specularscale > 0)
1315 permutation |= SHADERPERMUTATION_SPECULAR;
1316 if (r_refdef.fogenabled)
1317 permutation |= SHADERPERMUTATION_FOG;
1318 if (rsurface.texture->colormapping)
1319 permutation |= SHADERPERMUTATION_COLORMAPPING;
1320 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1321 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1322 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1323 permutation |= SHADERPERMUTATION_REFLECTION;
1325 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1327 // ambient model lighting
1328 mode = SHADERMODE_LIGHTDIRECTION;
1329 if (rsurface.texture->currentskinframe->glow)
1330 permutation |= SHADERPERMUTATION_GLOW;
1331 if (r_refdef.fogenabled)
1332 permutation |= SHADERPERMUTATION_FOG;
1333 if (rsurface.texture->colormapping)
1334 permutation |= SHADERPERMUTATION_COLORMAPPING;
1335 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1336 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1337 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1338 permutation |= SHADERPERMUTATION_REFLECTION;
1343 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1345 // deluxemapping (light direction texture)
1346 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1347 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1349 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1350 if (specularscale > 0)
1351 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1353 else if (r_glsl_deluxemapping.integer >= 2)
1355 // fake deluxemapping (uniform light direction in tangentspace)
1356 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1357 if (specularscale > 0)
1358 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1360 else if (rsurface.uselightmaptexture)
1362 // ordinary lightmapping (q1bsp, q3bsp)
1363 mode = SHADERMODE_LIGHTMAP;
1367 // ordinary vertex coloring (q3bsp)
1368 mode = SHADERMODE_VERTEXCOLOR;
1370 if (rsurface.texture->currentskinframe->glow)
1371 permutation |= SHADERPERMUTATION_GLOW;
1372 if (r_refdef.fogenabled)
1373 permutation |= SHADERPERMUTATION_FOG;
1374 if (rsurface.texture->colormapping)
1375 permutation |= SHADERPERMUTATION_COLORMAPPING;
1376 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1377 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1378 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1379 permutation |= SHADERPERMUTATION_REFLECTION;
1381 permutation |= mode * SHADERPERMUTATION_MODEBASE;
1382 if (!r_glsl_permutations[permutation].program)
1384 if (!r_glsl_permutations[permutation].compiled)
1385 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1386 if (!r_glsl_permutations[permutation].program)
1388 // remove features until we find a valid permutation
1390 for (i = (SHADERPERMUTATION_MODEBASE >> 1);;i>>=1)
1394 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");
1395 Cvar_SetValueQuick(&r_glsl, 0);
1396 return 0; // no bit left to clear
1398 // reduce i more quickly whenever it would not remove any bits
1399 if (!(permutation & i))
1402 if (!r_glsl_permutations[permutation].compiled)
1403 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1404 if (r_glsl_permutations[permutation].program)
1409 r_glsl_permutation = r_glsl_permutations + permutation;
1411 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1412 if (mode == SHADERMODE_LIGHTSOURCE)
1414 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1415 if (permutation & SHADERPERMUTATION_DIFFUSE)
1417 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1418 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1419 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1420 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1424 // ambient only is simpler
1425 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1426 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1427 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1428 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1431 else if (mode == SHADERMODE_LIGHTDIRECTION)
1433 if (r_glsl_permutation->loc_AmbientColor >= 0)
1434 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);
1435 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1436 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);
1437 if (r_glsl_permutation->loc_SpecularColor >= 0)
1438 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);
1439 if (r_glsl_permutation->loc_LightDir >= 0)
1440 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1444 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
1445 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1446 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1448 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]);
1449 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1450 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1452 // The formula used is actually:
1453 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1454 // color.rgb *= SceneBrightness;
1456 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1457 // and do [[calculations]] here in the engine
1458 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1459 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1462 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1463 if (r_glsl_permutation->loc_FogColor >= 0)
1465 // additive passes are only darkened by fog, not tinted
1466 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1467 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1469 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1471 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1472 if (r_glsl_permutation->loc_Color_Pants >= 0)
1474 if (rsurface.texture->currentskinframe->pants)
1475 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1477 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1479 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1481 if (rsurface.texture->currentskinframe->shirt)
1482 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1484 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1486 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1487 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1488 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1489 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);
1490 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]);
1491 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]);
1492 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1493 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1494 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1495 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1500 #define SKINFRAME_HASH 1024
1504 int loadsequence; // incremented each level change
1505 memexpandablearray_t array;
1506 skinframe_t *hash[SKINFRAME_HASH];
1510 void R_SkinFrame_PrepareForPurge(void)
1512 r_skinframe.loadsequence++;
1513 // wrap it without hitting zero
1514 if (r_skinframe.loadsequence >= 200)
1515 r_skinframe.loadsequence = 1;
1518 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1522 // mark the skinframe as used for the purging code
1523 skinframe->loadsequence = r_skinframe.loadsequence;
1526 void R_SkinFrame_Purge(void)
1530 for (i = 0;i < SKINFRAME_HASH;i++)
1532 for (s = r_skinframe.hash[i];s;s = s->next)
1534 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1536 if (s->merged == s->base)
1538 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1539 R_PurgeTexture(s->stain );s->stain = NULL;
1540 R_PurgeTexture(s->merged);s->merged = NULL;
1541 R_PurgeTexture(s->base );s->base = NULL;
1542 R_PurgeTexture(s->pants );s->pants = NULL;
1543 R_PurgeTexture(s->shirt );s->shirt = NULL;
1544 R_PurgeTexture(s->nmap );s->nmap = NULL;
1545 R_PurgeTexture(s->gloss );s->gloss = NULL;
1546 R_PurgeTexture(s->glow );s->glow = NULL;
1547 R_PurgeTexture(s->fog );s->fog = NULL;
1548 s->loadsequence = 0;
1554 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1556 char basename[MAX_QPATH];
1558 Image_StripImageExtension(name, basename, sizeof(basename));
1560 if( last == NULL ) {
1562 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1563 item = r_skinframe.hash[hashindex];
1568 // linearly search through the hash bucket
1569 for( ; item ; item = item->next ) {
1570 if( !strcmp( item->basename, basename ) ) {
1577 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1581 char basename[MAX_QPATH];
1583 Image_StripImageExtension(name, basename, sizeof(basename));
1585 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1586 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1587 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1591 rtexture_t *dyntexture;
1592 // check whether its a dynamic texture
1593 dyntexture = CL_GetDynTexture( basename );
1594 if (!add && !dyntexture)
1596 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1597 memset(item, 0, sizeof(*item));
1598 strlcpy(item->basename, basename, sizeof(item->basename));
1599 item->base = dyntexture; // either NULL or dyntexture handle
1600 item->textureflags = textureflags;
1601 item->comparewidth = comparewidth;
1602 item->compareheight = compareheight;
1603 item->comparecrc = comparecrc;
1604 item->next = r_skinframe.hash[hashindex];
1605 r_skinframe.hash[hashindex] = item;
1607 else if( item->base == NULL )
1609 rtexture_t *dyntexture;
1610 // check whether its a dynamic texture
1611 // 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]
1612 dyntexture = CL_GetDynTexture( basename );
1613 item->base = dyntexture; // either NULL or dyntexture handle
1616 R_SkinFrame_MarkUsed(item);
1620 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1622 // FIXME: it should be possible to disable loading various layers using
1623 // cvars, to prevent wasted loading time and memory usage if the user does
1625 qboolean loadnormalmap = true;
1626 qboolean loadgloss = true;
1627 qboolean loadpantsandshirt = true;
1628 qboolean loadglow = true;
1630 unsigned char *pixels;
1631 unsigned char *bumppixels;
1632 unsigned char *basepixels = NULL;
1633 int basepixels_width;
1634 int basepixels_height;
1635 skinframe_t *skinframe;
1637 if (cls.state == ca_dedicated)
1640 // return an existing skinframe if already loaded
1641 // if loading of the first image fails, don't make a new skinframe as it
1642 // would cause all future lookups of this to be missing
1643 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1644 if (skinframe && skinframe->base)
1647 basepixels = loadimagepixelsbgra(name, complain, true);
1648 if (basepixels == NULL)
1651 // we've got some pixels to store, so really allocate this new texture now
1653 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1654 skinframe->stain = NULL;
1655 skinframe->merged = NULL;
1656 skinframe->base = r_texture_notexture;
1657 skinframe->pants = NULL;
1658 skinframe->shirt = NULL;
1659 skinframe->nmap = r_texture_blanknormalmap;
1660 skinframe->gloss = NULL;
1661 skinframe->glow = NULL;
1662 skinframe->fog = NULL;
1664 basepixels_width = image_width;
1665 basepixels_height = image_height;
1666 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);
1668 if (textureflags & TEXF_ALPHA)
1670 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1671 if (basepixels[j] < 255)
1673 if (j < basepixels_width * basepixels_height * 4)
1675 // has transparent pixels
1676 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1677 for (j = 0;j < image_width * image_height * 4;j += 4)
1682 pixels[j+3] = basepixels[j+3];
1684 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);
1689 // _norm is the name used by tenebrae and has been adopted as standard
1692 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1694 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);
1698 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1700 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1701 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1702 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);
1704 Mem_Free(bumppixels);
1706 else if (r_shadow_bumpscale_basetexture.value > 0)
1708 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1709 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1710 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);
1714 // _luma is supported for tenebrae compatibility
1715 // (I think it's a very stupid name, but oh well)
1716 // _glow is the preferred name
1717 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;}
1718 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;}
1719 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;}
1720 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;}
1723 Mem_Free(basepixels);
1728 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)
1733 for (i = 0;i < width*height;i++)
1734 if (((unsigned char *)&palette[in[i]])[3] > 0)
1736 if (i == width*height)
1739 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1742 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
1743 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
1746 unsigned char *temp1, *temp2;
1747 skinframe_t *skinframe;
1749 if (cls.state == ca_dedicated)
1752 // if already loaded just return it, otherwise make a new skinframe
1753 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
1754 if (skinframe && skinframe->base)
1757 skinframe->stain = NULL;
1758 skinframe->merged = NULL;
1759 skinframe->base = r_texture_notexture;
1760 skinframe->pants = NULL;
1761 skinframe->shirt = NULL;
1762 skinframe->nmap = r_texture_blanknormalmap;
1763 skinframe->gloss = NULL;
1764 skinframe->glow = NULL;
1765 skinframe->fog = NULL;
1767 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1771 if (r_shadow_bumpscale_basetexture.value > 0)
1773 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1774 temp2 = temp1 + width * height * 4;
1775 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1776 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1779 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1780 if (textureflags & TEXF_ALPHA)
1782 for (i = 3;i < width * height * 4;i += 4)
1783 if (skindata[i] < 255)
1785 if (i < width * height * 4)
1787 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1788 memcpy(fogpixels, skindata, width * height * 4);
1789 for (i = 0;i < width * height * 4;i += 4)
1790 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1791 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1792 Mem_Free(fogpixels);
1799 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
1802 unsigned char *temp1, *temp2;
1803 skinframe_t *skinframe;
1805 if (cls.state == ca_dedicated)
1808 // if already loaded just return it, otherwise make a new skinframe
1809 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
1810 if (skinframe && skinframe->base)
1813 skinframe->stain = NULL;
1814 skinframe->merged = NULL;
1815 skinframe->base = r_texture_notexture;
1816 skinframe->pants = NULL;
1817 skinframe->shirt = NULL;
1818 skinframe->nmap = r_texture_blanknormalmap;
1819 skinframe->gloss = NULL;
1820 skinframe->glow = NULL;
1821 skinframe->fog = NULL;
1823 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1827 if (r_shadow_bumpscale_basetexture.value > 0)
1829 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1830 temp2 = temp1 + width * height * 4;
1831 // use either a custom palette or the quake palette
1832 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
1833 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1834 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1837 // use either a custom palette, or the quake palette
1838 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
1839 if (loadglowtexture)
1840 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
1841 if (loadpantsandshirt)
1843 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
1844 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
1846 if (skinframe->pants || skinframe->shirt)
1847 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
1848 if (textureflags & TEXF_ALPHA)
1850 for (i = 0;i < width * height;i++)
1851 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
1853 if (i < width * height)
1854 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
1860 skinframe_t *R_SkinFrame_LoadMissing(void)
1862 skinframe_t *skinframe;
1864 if (cls.state == ca_dedicated)
1867 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1868 skinframe->stain = NULL;
1869 skinframe->merged = NULL;
1870 skinframe->base = r_texture_notexture;
1871 skinframe->pants = NULL;
1872 skinframe->shirt = NULL;
1873 skinframe->nmap = r_texture_blanknormalmap;
1874 skinframe->gloss = NULL;
1875 skinframe->glow = NULL;
1876 skinframe->fog = NULL;
1881 void gl_main_start(void)
1883 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1884 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1886 // set up r_skinframe loading system for textures
1887 memset(&r_skinframe, 0, sizeof(r_skinframe));
1888 r_skinframe.loadsequence = 1;
1889 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1891 r_main_texturepool = R_AllocTexturePool();
1892 R_BuildBlankTextures();
1894 if (gl_texturecubemap)
1897 R_BuildNormalizationCube();
1899 r_texture_fogattenuation = NULL;
1900 //r_texture_fogintensity = NULL;
1901 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1902 memset(&r_waterstate, 0, sizeof(r_waterstate));
1903 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1904 memset(&r_svbsp, 0, sizeof (r_svbsp));
1906 r_refdef.fogmasktable_density = 0;
1909 void gl_main_shutdown(void)
1911 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1912 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1914 // clear out the r_skinframe state
1915 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
1916 memset(&r_skinframe, 0, sizeof(r_skinframe));
1919 Mem_Free(r_svbsp.nodes);
1920 memset(&r_svbsp, 0, sizeof (r_svbsp));
1921 R_FreeTexturePool(&r_main_texturepool);
1922 r_texture_blanknormalmap = NULL;
1923 r_texture_white = NULL;
1924 r_texture_grey128 = NULL;
1925 r_texture_black = NULL;
1926 r_texture_whitecube = NULL;
1927 r_texture_normalizationcube = NULL;
1928 r_texture_fogattenuation = NULL;
1929 //r_texture_fogintensity = NULL;
1930 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1931 memset(&r_waterstate, 0, sizeof(r_waterstate));
1935 extern void CL_ParseEntityLump(char *entitystring);
1936 void gl_main_newmap(void)
1938 // FIXME: move this code to client
1940 char *entities, entname[MAX_QPATH];
1943 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
1944 l = (int)strlen(entname) - 4;
1945 if (l >= 0 && !strcmp(entname + l, ".bsp"))
1947 memcpy(entname + l, ".ent", 5);
1948 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
1950 CL_ParseEntityLump(entities);
1955 if (cl.worldmodel->brush.entities)
1956 CL_ParseEntityLump(cl.worldmodel->brush.entities);
1960 void GL_Main_Init(void)
1962 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
1964 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
1965 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
1966 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
1967 if (gamemode == GAME_NEHAHRA)
1969 Cvar_RegisterVariable (&gl_fogenable);
1970 Cvar_RegisterVariable (&gl_fogdensity);
1971 Cvar_RegisterVariable (&gl_fogred);
1972 Cvar_RegisterVariable (&gl_foggreen);
1973 Cvar_RegisterVariable (&gl_fogblue);
1974 Cvar_RegisterVariable (&gl_fogstart);
1975 Cvar_RegisterVariable (&gl_fogend);
1976 Cvar_RegisterVariable (&gl_skyclip);
1978 Cvar_RegisterVariable(&r_depthfirst);
1979 Cvar_RegisterVariable(&r_nearclip);
1980 Cvar_RegisterVariable(&r_showbboxes);
1981 Cvar_RegisterVariable(&r_showsurfaces);
1982 Cvar_RegisterVariable(&r_showtris);
1983 Cvar_RegisterVariable(&r_shownormals);
1984 Cvar_RegisterVariable(&r_showlighting);
1985 Cvar_RegisterVariable(&r_showshadowvolumes);
1986 Cvar_RegisterVariable(&r_showcollisionbrushes);
1987 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
1988 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
1989 Cvar_RegisterVariable(&r_showdisabledepthtest);
1990 Cvar_RegisterVariable(&r_drawportals);
1991 Cvar_RegisterVariable(&r_drawentities);
1992 Cvar_RegisterVariable(&r_cullentities_trace);
1993 Cvar_RegisterVariable(&r_cullentities_trace_samples);
1994 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
1995 Cvar_RegisterVariable(&r_cullentities_trace_delay);
1996 Cvar_RegisterVariable(&r_drawviewmodel);
1997 Cvar_RegisterVariable(&r_speeds);
1998 Cvar_RegisterVariable(&r_fullbrights);
1999 Cvar_RegisterVariable(&r_wateralpha);
2000 Cvar_RegisterVariable(&r_dynamic);
2001 Cvar_RegisterVariable(&r_fullbright);
2002 Cvar_RegisterVariable(&r_shadows);
2003 Cvar_RegisterVariable(&r_shadows_throwdistance);
2004 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2005 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2006 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2007 Cvar_RegisterVariable(&r_fog_exp2);
2008 Cvar_RegisterVariable(&r_textureunits);
2009 Cvar_RegisterVariable(&r_glsl);
2010 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2011 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2012 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2013 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2014 Cvar_RegisterVariable(&r_water);
2015 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2016 Cvar_RegisterVariable(&r_water_clippingplanebias);
2017 Cvar_RegisterVariable(&r_water_refractdistort);
2018 Cvar_RegisterVariable(&r_water_reflectdistort);
2019 Cvar_RegisterVariable(&r_lerpsprites);
2020 Cvar_RegisterVariable(&r_lerpmodels);
2021 Cvar_RegisterVariable(&r_lerplightstyles);
2022 Cvar_RegisterVariable(&r_waterscroll);
2023 Cvar_RegisterVariable(&r_bloom);
2024 Cvar_RegisterVariable(&r_bloom_colorscale);
2025 Cvar_RegisterVariable(&r_bloom_brighten);
2026 Cvar_RegisterVariable(&r_bloom_blur);
2027 Cvar_RegisterVariable(&r_bloom_resolution);
2028 Cvar_RegisterVariable(&r_bloom_colorexponent);
2029 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2030 Cvar_RegisterVariable(&r_hdr);
2031 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2032 Cvar_RegisterVariable(&r_glsl_contrastboost);
2033 Cvar_RegisterVariable(&r_hdr_glowintensity);
2034 Cvar_RegisterVariable(&r_hdr_range);
2035 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2036 Cvar_RegisterVariable(&developer_texturelogging);
2037 Cvar_RegisterVariable(&gl_lightmaps);
2038 Cvar_RegisterVariable(&r_test);
2039 Cvar_RegisterVariable(&r_batchmode);
2040 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2041 Cvar_SetValue("r_fullbrights", 0);
2042 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2044 Cvar_RegisterVariable(&r_track_sprites);
2045 Cvar_RegisterVariable(&r_track_sprites_flags);
2046 Cvar_RegisterVariable(&r_track_sprites_scalew);
2047 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2050 extern void R_Textures_Init(void);
2051 extern void GL_Draw_Init(void);
2052 extern void GL_Main_Init(void);
2053 extern void R_Shadow_Init(void);
2054 extern void R_Sky_Init(void);
2055 extern void GL_Surf_Init(void);
2056 extern void R_Particles_Init(void);
2057 extern void R_Explosion_Init(void);
2058 extern void gl_backend_init(void);
2059 extern void Sbar_Init(void);
2060 extern void R_LightningBeams_Init(void);
2061 extern void Mod_RenderInit(void);
2063 void Render_Init(void)
2075 R_LightningBeams_Init();
2084 extern char *ENGINE_EXTENSIONS;
2087 VID_CheckExtensions();
2089 // LordHavoc: report supported extensions
2090 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2092 // clear to black (loading plaque will be seen over this)
2094 qglClearColor(0,0,0,1);CHECKGLERROR
2095 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2098 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2102 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2104 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2107 p = r_refdef.view.frustum + i;
2112 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2116 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2120 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2124 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2128 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2132 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2136 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2140 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2148 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2152 for (i = 0;i < numplanes;i++)
2159 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2163 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2167 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2171 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2175 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2179 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2183 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2187 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2195 //==================================================================================
2197 static void R_View_UpdateEntityVisible (void)
2200 entity_render_t *ent;
2202 if (!r_drawentities.integer)
2205 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2206 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
2208 // worldmodel can check visibility
2209 for (i = 0;i < r_refdef.numentities;i++)
2211 ent = r_refdef.entities[i];
2212 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.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs));
2215 if(r_cullentities_trace.integer && r_refdef.worldmodel->brush.TraceLineOfSight)
2217 for (i = 0;i < r_refdef.numentities;i++)
2219 ent = r_refdef.entities[i];
2220 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2222 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_refdef.view.origin, ent->mins, ent->maxs))
2223 ent->last_trace_visibility = realtime;
2224 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2225 r_refdef.viewcache.entityvisible[i] = 0;
2232 // no worldmodel or it can't check visibility
2233 for (i = 0;i < r_refdef.numentities;i++)
2235 ent = r_refdef.entities[i];
2236 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));
2241 // only used if skyrendermasked, and normally returns false
2242 int R_DrawBrushModelsSky (void)
2245 entity_render_t *ent;
2247 if (!r_drawentities.integer)
2251 for (i = 0;i < r_refdef.numentities;i++)
2253 if (!r_refdef.viewcache.entityvisible[i])
2255 ent = r_refdef.entities[i];
2256 if (!ent->model || !ent->model->DrawSky)
2258 ent->model->DrawSky(ent);
2264 static void R_DrawNoModel(entity_render_t *ent);
2265 static void R_DrawModels(void)
2268 entity_render_t *ent;
2270 if (!r_drawentities.integer)
2273 for (i = 0;i < r_refdef.numentities;i++)
2275 if (!r_refdef.viewcache.entityvisible[i])
2277 ent = r_refdef.entities[i];
2278 r_refdef.stats.entities++;
2279 if (ent->model && ent->model->Draw != NULL)
2280 ent->model->Draw(ent);
2286 static void R_DrawModelsDepth(void)
2289 entity_render_t *ent;
2291 if (!r_drawentities.integer)
2294 for (i = 0;i < r_refdef.numentities;i++)
2296 if (!r_refdef.viewcache.entityvisible[i])
2298 ent = r_refdef.entities[i];
2299 if (ent->model && ent->model->DrawDepth != NULL)
2300 ent->model->DrawDepth(ent);
2304 static void R_DrawModelsDebug(void)
2307 entity_render_t *ent;
2309 if (!r_drawentities.integer)
2312 for (i = 0;i < r_refdef.numentities;i++)
2314 if (!r_refdef.viewcache.entityvisible[i])
2316 ent = r_refdef.entities[i];
2317 if (ent->model && ent->model->DrawDebug != NULL)
2318 ent->model->DrawDebug(ent);
2322 static void R_DrawModelsAddWaterPlanes(void)
2325 entity_render_t *ent;
2327 if (!r_drawentities.integer)
2330 for (i = 0;i < r_refdef.numentities;i++)
2332 if (!r_refdef.viewcache.entityvisible[i])
2334 ent = r_refdef.entities[i];
2335 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2336 ent->model->DrawAddWaterPlanes(ent);
2340 static void R_View_SetFrustum(void)
2343 double slopex, slopey;
2345 // break apart the view matrix into vectors for various purposes
2346 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
2347 VectorNegate(r_refdef.view.left, r_refdef.view.right);
2350 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2351 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2352 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2353 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2354 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2355 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2356 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2357 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2358 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2359 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2360 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2361 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2365 zNear = r_refdef.nearclip;
2366 nudge = 1.0 - 1.0 / (1<<23);
2367 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2368 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2369 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2370 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2371 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2372 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2373 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2374 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2380 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2381 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2382 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2383 r_refdef.view.frustum[0].dist = m[15] - m[12];
2385 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2386 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2387 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2388 r_refdef.view.frustum[1].dist = m[15] + m[12];
2390 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2391 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2392 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2393 r_refdef.view.frustum[2].dist = m[15] - m[13];
2395 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2396 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2397 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2398 r_refdef.view.frustum[3].dist = m[15] + m[13];
2400 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2401 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2402 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2403 r_refdef.view.frustum[4].dist = m[15] - m[14];
2405 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2406 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2407 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2408 r_refdef.view.frustum[5].dist = m[15] + m[14];
2411 if (r_refdef.view.useperspective)
2413 slopex = 1.0 / r_refdef.view.frustum_x;
2414 slopey = 1.0 / r_refdef.view.frustum_y;
2415 VectorMA(r_refdef.view.forward, -slopex, r_refdef.view.left, r_refdef.view.frustum[0].normal);
2416 VectorMA(r_refdef.view.forward, slopex, r_refdef.view.left, r_refdef.view.frustum[1].normal);
2417 VectorMA(r_refdef.view.forward, -slopey, r_refdef.view.up , r_refdef.view.frustum[2].normal);
2418 VectorMA(r_refdef.view.forward, slopey, r_refdef.view.up , r_refdef.view.frustum[3].normal);
2419 VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
2421 // Leaving those out was a mistake, those were in the old code, and they
2422 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2423 // I couldn't reproduce it after adding those normalizations. --blub
2424 VectorNormalize(r_refdef.view.frustum[0].normal);
2425 VectorNormalize(r_refdef.view.frustum[1].normal);
2426 VectorNormalize(r_refdef.view.frustum[2].normal);
2427 VectorNormalize(r_refdef.view.frustum[3].normal);
2429 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2430 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]);
2431 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]);
2432 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]);
2433 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]);
2435 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2436 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2437 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2438 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2439 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2443 VectorScale(r_refdef.view.left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2444 VectorScale(r_refdef.view.left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2445 VectorScale(r_refdef.view.up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2446 VectorScale(r_refdef.view.up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2447 VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
2448 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2449 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2450 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2451 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2452 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2454 r_refdef.view.numfrustumplanes = 5;
2456 if (r_refdef.view.useclipplane)
2458 r_refdef.view.numfrustumplanes = 6;
2459 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2462 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2463 PlaneClassify(r_refdef.view.frustum + i);
2465 // LordHavoc: note to all quake engine coders, Quake had a special case
2466 // for 90 degrees which assumed a square view (wrong), so I removed it,
2467 // Quake2 has it disabled as well.
2469 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2470 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, r_refdef.view.up, r_refdef.view.forward, -(90 - r_refdef.fov_x / 2));
2471 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2472 //PlaneClassify(&frustum[0]);
2474 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2475 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, r_refdef.view.up, r_refdef.view.forward, (90 - r_refdef.fov_x / 2));
2476 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2477 //PlaneClassify(&frustum[1]);
2479 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2480 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, r_refdef.view.left, r_refdef.view.forward, -(90 - r_refdef.fov_y / 2));
2481 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2482 //PlaneClassify(&frustum[2]);
2484 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2485 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, r_refdef.view.left, r_refdef.view.forward, (90 - r_refdef.fov_y / 2));
2486 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2487 //PlaneClassify(&frustum[3]);
2490 //VectorCopy(r_refdef.view.forward, r_refdef.view.frustum[4].normal);
2491 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2492 //PlaneClassify(&frustum[4]);
2495 void R_View_Update(void)
2497 R_View_SetFrustum();
2498 R_View_WorldVisibility(r_refdef.view.useclipplane);
2499 R_View_UpdateEntityVisible();
2502 void R_SetupView(void)
2504 if (!r_refdef.view.useperspective)
2505 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);
2506 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2507 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2509 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2511 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2513 if (r_refdef.view.useclipplane)
2515 // LordHavoc: couldn't figure out how to make this approach the
2516 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2517 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2518 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2519 dist = r_refdef.view.clipplane.dist;
2520 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2524 void R_ResetViewRendering2D(void)
2526 if (gl_support_fragment_shader)
2528 qglUseProgramObjectARB(0);CHECKGLERROR
2533 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2534 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2535 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2536 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2537 GL_Color(1, 1, 1, 1);
2538 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2539 GL_BlendFunc(GL_ONE, GL_ZERO);
2540 GL_AlphaTest(false);
2541 GL_ScissorTest(false);
2542 GL_DepthMask(false);
2543 GL_DepthRange(0, 1);
2544 GL_DepthTest(false);
2545 R_Mesh_Matrix(&identitymatrix);
2546 R_Mesh_ResetTextureState();
2547 GL_PolygonOffset(0, 0);
2548 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2549 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2550 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2551 qglStencilMask(~0);CHECKGLERROR
2552 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2553 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2554 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2557 void R_ResetViewRendering3D(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
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(true);
2576 GL_DepthRange(0, 1);
2578 R_Mesh_Matrix(&identitymatrix);
2579 R_Mesh_ResetTextureState();
2580 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
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(r_refdef.view.cullface_back);
2591 R_Bloom_SetupShader(
2593 "// written by Forest 'LordHavoc' Hale\n"
2595 "// common definitions between vertex shader and fragment shader:\n"
2597 "#ifdef __GLSL_CG_DATA_TYPES\n"
2598 "#define myhalf half\n"
2599 "#define myhvec2 hvec2\n"
2600 "#define myhvec3 hvec3\n"
2601 "#define myhvec4 hvec4\n"
2603 "#define myhalf float\n"
2604 "#define myhvec2 vec2\n"
2605 "#define myhvec3 vec3\n"
2606 "#define myhvec4 vec4\n"
2609 "varying vec2 ScreenTexCoord;\n"
2610 "varying vec2 BloomTexCoord;\n"
2615 "// vertex shader specific:\n"
2616 "#ifdef VERTEX_SHADER\n"
2620 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2621 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2622 " // transform vertex to camera space, using ftransform to match non-VS\n"
2624 " gl_Position = ftransform();\n"
2627 "#endif // VERTEX_SHADER\n"
2632 "// fragment shader specific:\n"
2633 "#ifdef FRAGMENT_SHADER\n"
2638 " myhvec3 color = myhvec3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2639 " for (x = -BLUR_X;x <= BLUR_X;x++)
2640 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2641 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2642 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2643 " color.rgb += myhvec3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2645 " gl_FragColor = vec4(color);\n"
2648 "#endif // FRAGMENT_SHADER\n"
2651 void R_RenderScene(qboolean addwaterplanes);
2653 static void R_Water_StartFrame(void)
2656 int waterwidth, waterheight, texturewidth, textureheight;
2657 r_waterstate_waterplane_t *p;
2659 // set waterwidth and waterheight to the water resolution that will be
2660 // used (often less than the screen resolution for faster rendering)
2661 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
2662 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
2664 // calculate desired texture sizes
2665 // can't use water if the card does not support the texture size
2666 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2667 texturewidth = textureheight = waterwidth = waterheight = 0;
2668 else if (gl_support_arb_texture_non_power_of_two)
2670 texturewidth = waterwidth;
2671 textureheight = waterheight;
2675 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2676 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2679 // allocate textures as needed
2680 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2682 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2683 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2685 if (p->texture_refraction)
2686 R_FreeTexture(p->texture_refraction);
2687 p->texture_refraction = NULL;
2688 if (p->texture_reflection)
2689 R_FreeTexture(p->texture_reflection);
2690 p->texture_reflection = NULL;
2692 memset(&r_waterstate, 0, sizeof(r_waterstate));
2693 r_waterstate.waterwidth = waterwidth;
2694 r_waterstate.waterheight = waterheight;
2695 r_waterstate.texturewidth = texturewidth;
2696 r_waterstate.textureheight = textureheight;
2699 if (r_waterstate.waterwidth)
2701 r_waterstate.enabled = true;
2703 // set up variables that will be used in shader setup
2704 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2705 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2706 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2707 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2710 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2711 r_waterstate.numwaterplanes = 0;
2714 static void R_Water_AddWaterPlane(msurface_t *surface)
2716 int triangleindex, planeindex;
2721 r_waterstate_waterplane_t *p;
2722 // just use the first triangle with a valid normal for any decisions
2723 VectorClear(normal);
2724 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2726 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2727 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2728 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2729 TriangleNormal(vert[0], vert[1], vert[2], normal);
2730 if (VectorLength2(normal) >= 0.001)
2734 // find a matching plane if there is one
2735 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2736 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2738 if (planeindex >= r_waterstate.maxwaterplanes)
2739 return; // nothing we can do, out of planes
2741 // if this triangle does not fit any known plane rendered this frame, add one
2742 if (planeindex >= r_waterstate.numwaterplanes)
2744 // store the new plane
2745 r_waterstate.numwaterplanes++;
2746 VectorCopy(normal, p->plane.normal);
2747 VectorNormalize(p->plane.normal);
2748 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2749 PlaneClassify(&p->plane);
2750 // flip the plane if it does not face the viewer
2751 if (PlaneDiff(r_refdef.view.origin, &p->plane) < 0)
2753 VectorNegate(p->plane.normal, p->plane.normal);
2754 p->plane.dist *= -1;
2755 PlaneClassify(&p->plane);
2757 // clear materialflags and pvs
2758 p->materialflags = 0;
2759 p->pvsvalid = false;
2761 // merge this surface's materialflags into the waterplane
2762 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2763 // merge this surface's PVS into the waterplane
2764 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
2765 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.worldmodel && r_refdef.worldmodel->brush.FatPVS
2766 && r_refdef.worldmodel->brush.PointInLeaf && r_refdef.worldmodel->brush.PointInLeaf(r_refdef.worldmodel, center)->clusterindex >= 0)
2768 r_refdef.worldmodel->brush.FatPVS(r_refdef.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2773 static void R_Water_ProcessPlanes(void)
2775 r_refdef_view_t originalview;
2777 r_waterstate_waterplane_t *p;
2779 originalview = r_refdef.view;
2781 // make sure enough textures are allocated
2782 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2784 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2786 if (!p->texture_refraction)
2787 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);
2788 if (!p->texture_refraction)
2792 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2794 if (!p->texture_reflection)
2795 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);
2796 if (!p->texture_reflection)
2802 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2804 r_refdef.view.showdebug = false;
2805 r_refdef.view.width = r_waterstate.waterwidth;
2806 r_refdef.view.height = r_waterstate.waterheight;
2807 r_refdef.view.useclipplane = true;
2808 r_waterstate.renderingscene = true;
2810 // render the normal view scene and copy into texture
2811 // (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)
2812 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2814 r_refdef.view.clipplane = p->plane;
2815 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
2816 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
2817 PlaneClassify(&r_refdef.view.clipplane);
2819 R_RenderScene(false);
2821 // copy view into the screen texture
2822 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2823 GL_ActiveTexture(0);
2825 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
2828 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2830 // render reflected scene and copy into texture
2831 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2832 r_refdef.view.clipplane = p->plane;
2833 // reverse the cullface settings for this render
2834 r_refdef.view.cullface_front = GL_FRONT;
2835 r_refdef.view.cullface_back = GL_BACK;
2836 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2838 r_refdef.view.usecustompvs = true;
2840 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2842 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2845 R_ResetViewRendering3D();
2846 R_ClearScreen(r_refdef.fogenabled);
2847 if (r_timereport_active)
2848 R_TimeReport("viewclear");
2850 R_RenderScene(false);
2852 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
2853 GL_ActiveTexture(0);
2855 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
2857 R_ResetViewRendering3D();
2858 R_ClearScreen(r_refdef.fogenabled);
2859 if (r_timereport_active)
2860 R_TimeReport("viewclear");
2863 r_refdef.view = originalview;
2864 r_refdef.view.clear = true;
2865 r_waterstate.renderingscene = false;
2869 r_refdef.view = originalview;
2870 r_waterstate.renderingscene = false;
2871 Cvar_SetValueQuick(&r_water, 0);
2872 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
2876 void R_Bloom_StartFrame(void)
2878 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
2880 // set bloomwidth and bloomheight to the bloom resolution that will be
2881 // used (often less than the screen resolution for faster rendering)
2882 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
2883 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
2884 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
2886 // calculate desired texture sizes
2887 if (gl_support_arb_texture_non_power_of_two)
2889 screentexturewidth = r_refdef.view.width;
2890 screentextureheight = r_refdef.view.height;
2891 bloomtexturewidth = r_bloomstate.bloomwidth;
2892 bloomtextureheight = r_bloomstate.bloomheight;
2896 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
2897 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
2898 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
2899 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
2904 screentexturewidth = screentextureheight = 0;
2906 else if (r_bloom.integer)
2911 screentexturewidth = screentextureheight = 0;
2912 bloomtexturewidth = bloomtextureheight = 0;
2915 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)
2917 // can't use bloom if the parameters are too weird
2918 // can't use bloom if the card does not support the texture size
2919 if (r_bloomstate.texture_screen)
2920 R_FreeTexture(r_bloomstate.texture_screen);
2921 if (r_bloomstate.texture_bloom)
2922 R_FreeTexture(r_bloomstate.texture_bloom);
2923 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2927 r_bloomstate.enabled = true;
2928 r_bloomstate.hdr = r_hdr.integer != 0;
2930 // allocate textures as needed
2931 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
2933 if (r_bloomstate.texture_screen)
2934 R_FreeTexture(r_bloomstate.texture_screen);
2935 r_bloomstate.texture_screen = NULL;
2936 r_bloomstate.screentexturewidth = screentexturewidth;
2937 r_bloomstate.screentextureheight = screentextureheight;
2938 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
2939 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);
2941 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
2943 if (r_bloomstate.texture_bloom)
2944 R_FreeTexture(r_bloomstate.texture_bloom);
2945 r_bloomstate.texture_bloom = NULL;
2946 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
2947 r_bloomstate.bloomtextureheight = bloomtextureheight;
2948 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
2949 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);
2952 // set up a texcoord array for the full resolution screen image
2953 // (we have to keep this around to copy back during final render)
2954 r_bloomstate.screentexcoord2f[0] = 0;
2955 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
2956 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
2957 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
2958 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
2959 r_bloomstate.screentexcoord2f[5] = 0;
2960 r_bloomstate.screentexcoord2f[6] = 0;
2961 r_bloomstate.screentexcoord2f[7] = 0;
2963 // set up a texcoord array for the reduced resolution bloom image
2964 // (which will be additive blended over the screen image)
2965 r_bloomstate.bloomtexcoord2f[0] = 0;
2966 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2967 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2968 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
2969 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
2970 r_bloomstate.bloomtexcoord2f[5] = 0;
2971 r_bloomstate.bloomtexcoord2f[6] = 0;
2972 r_bloomstate.bloomtexcoord2f[7] = 0;
2975 void R_Bloom_CopyScreenTexture(float colorscale)
2977 r_refdef.stats.bloom++;
2979 R_ResetViewRendering2D();
2980 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
2981 R_Mesh_ColorPointer(NULL, 0, 0);
2982 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
2983 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
2985 // copy view into the screen texture
2986 GL_ActiveTexture(0);
2988 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
2989 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
2991 // now scale it down to the bloom texture size
2993 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
2994 GL_BlendFunc(GL_ONE, GL_ZERO);
2995 GL_Color(colorscale, colorscale, colorscale, 1);
2996 // TODO: optimize with multitexture or GLSL
2997 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
2998 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3000 // we now have a bloom image in the framebuffer
3001 // copy it into the bloom image texture for later processing
3002 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3003 GL_ActiveTexture(0);
3005 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
3006 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3009 void R_Bloom_CopyHDRTexture(void)
3011 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3012 GL_ActiveTexture(0);
3014 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
3015 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3018 void R_Bloom_MakeTexture(void)
3021 float xoffset, yoffset, r, brighten;
3023 r_refdef.stats.bloom++;
3025 R_ResetViewRendering2D();
3026 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3027 R_Mesh_ColorPointer(NULL, 0, 0);
3029 // we have a bloom image in the framebuffer
3031 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3033 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3036 r = bound(0, r_bloom_colorexponent.value / x, 1);
3037 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3038 GL_Color(r, r, r, 1);
3039 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3040 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3041 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3042 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3044 // copy the vertically blurred bloom view to a texture
3045 GL_ActiveTexture(0);
3047 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
3048 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3051 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3052 brighten = r_bloom_brighten.value;
3054 brighten *= r_hdr_range.value;
3055 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3056 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3058 for (dir = 0;dir < 2;dir++)
3060 // blend on at multiple vertical offsets to achieve a vertical blur
3061 // TODO: do offset blends using GLSL
3062 GL_BlendFunc(GL_ONE, GL_ZERO);
3063 for (x = -range;x <= range;x++)
3065 if (!dir){xoffset = 0;yoffset = x;}
3066 else {xoffset = x;yoffset = 0;}
3067 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3068 yoffset /= (float)r_bloomstate.bloomtextureheight;
3069 // compute a texcoord array with the specified x and y offset
3070 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3071 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3072 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3073 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3074 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3075 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3076 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3077 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3078 // this r value looks like a 'dot' particle, fading sharply to
3079 // black at the edges
3080 // (probably not realistic but looks good enough)
3081 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3082 //r = (dir ? 1.0f : brighten)/(range*2+1);
3083 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3084 GL_Color(r, r, r, 1);
3085 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3086 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3087 GL_BlendFunc(GL_ONE, GL_ONE);
3090 // copy the vertically blurred bloom view to a texture
3091 GL_ActiveTexture(0);
3093 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
3094 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3097 // apply subtract last
3098 // (just like it would be in a GLSL shader)
3099 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3101 GL_BlendFunc(GL_ONE, GL_ZERO);
3102 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3103 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3104 GL_Color(1, 1, 1, 1);
3105 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3106 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3108 GL_BlendFunc(GL_ONE, GL_ONE);
3109 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3110 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3111 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3112 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3113 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3114 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3115 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3117 // copy the darkened bloom view to a texture
3118 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3119 GL_ActiveTexture(0);
3121 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
3122 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3126 void R_HDR_RenderBloomTexture(void)
3128 int oldwidth, oldheight;
3129 float oldcolorscale;
3131 oldcolorscale = r_refdef.view.colorscale;
3132 oldwidth = r_refdef.view.width;
3133 oldheight = r_refdef.view.height;
3134 r_refdef.view.width = r_bloomstate.bloomwidth;
3135 r_refdef.view.height = r_bloomstate.bloomheight;
3137 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3138 // TODO: add exposure compensation features
3139 // TODO: add fp16 framebuffer support
3141 r_refdef.view.showdebug = false;
3142 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3144 R_ClearScreen(r_refdef.fogenabled);
3145 if (r_timereport_active)
3146 R_TimeReport("HDRclear");
3148 r_waterstate.numwaterplanes = 0;
3149 R_RenderScene(r_waterstate.enabled);
3150 r_refdef.view.showdebug = true;
3152 R_ResetViewRendering2D();
3154 R_Bloom_CopyHDRTexture();
3155 R_Bloom_MakeTexture();
3157 // restore the view settings
3158 r_refdef.view.width = oldwidth;
3159 r_refdef.view.height = oldheight;
3160 r_refdef.view.colorscale = oldcolorscale;
3162 R_ResetViewRendering3D();
3164 R_ClearScreen(r_refdef.fogenabled);
3165 if (r_timereport_active)
3166 R_TimeReport("viewclear");
3169 static void R_BlendView(void)
3171 if (r_bloomstate.enabled && r_bloomstate.hdr)
3173 // render high dynamic range bloom effect
3174 // the bloom texture was made earlier this render, so we just need to
3175 // blend it onto the screen...
3176 R_ResetViewRendering2D();
3177 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3178 R_Mesh_ColorPointer(NULL, 0, 0);
3179 GL_Color(1, 1, 1, 1);
3180 GL_BlendFunc(GL_ONE, GL_ONE);
3181 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3182 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3183 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3184 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3186 else if (r_bloomstate.enabled)
3188 // render simple bloom effect
3189 // copy the screen and shrink it and darken it for the bloom process
3190 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
3191 // make the bloom texture
3192 R_Bloom_MakeTexture();
3193 // put the original screen image back in place and blend the bloom
3195 R_ResetViewRendering2D();
3196 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3197 R_Mesh_ColorPointer(NULL, 0, 0);
3198 GL_Color(1, 1, 1, 1);
3199 GL_BlendFunc(GL_ONE, GL_ZERO);
3200 // do both in one pass if possible
3201 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3202 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3203 if (r_textureunits.integer >= 2 && gl_combine.integer)
3205 R_Mesh_TexCombine(1, GL_ADD, GL_ADD, 1, 1);
3206 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3207 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3211 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3212 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3213 // now blend on the bloom texture
3214 GL_BlendFunc(GL_ONE, GL_ONE);
3215 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3216 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3218 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3219 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3221 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3223 // apply a color tint to the whole view
3224 R_ResetViewRendering2D();
3225 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3226 R_Mesh_ColorPointer(NULL, 0, 0);
3227 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3228 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3229 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3233 void R_RenderScene(qboolean addwaterplanes);
3235 matrix4x4_t r_waterscrollmatrix;
3237 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3239 if (r_refdef.fog_density)
3241 r_refdef.fogcolor[0] = r_refdef.fog_red;
3242 r_refdef.fogcolor[1] = r_refdef.fog_green;
3243 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3247 VectorCopy(r_refdef.fogcolor, fogvec);
3248 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3250 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3251 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3252 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3253 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3255 // color.rgb *= ContrastBoost * SceneBrightness;
3256 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3257 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3258 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3259 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3264 void R_UpdateVariables(void)
3268 r_refdef.farclip = 4096;
3269 if (r_refdef.worldmodel)
3270 r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
3271 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3273 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3274 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3275 r_refdef.polygonfactor = 0;
3276 r_refdef.polygonoffset = 0;
3277 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3278 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3280 r_refdef.rtworld = r_shadow_realtime_world.integer;
3281 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3282 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3283 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3284 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3285 if (r_showsurfaces.integer)
3287 r_refdef.rtworld = false;
3288 r_refdef.rtworldshadows = false;
3289 r_refdef.rtdlight = false;
3290 r_refdef.rtdlightshadows = false;
3291 r_refdef.lightmapintensity = 0;
3294 if (gamemode == GAME_NEHAHRA)
3296 if (gl_fogenable.integer)
3298 r_refdef.oldgl_fogenable = true;
3299 r_refdef.fog_density = gl_fogdensity.value;
3300 r_refdef.fog_red = gl_fogred.value;
3301 r_refdef.fog_green = gl_foggreen.value;
3302 r_refdef.fog_blue = gl_fogblue.value;
3303 r_refdef.fog_alpha = 1;
3304 r_refdef.fog_start = 0;
3305 r_refdef.fog_end = gl_skyclip.value;
3307 else if (r_refdef.oldgl_fogenable)
3309 r_refdef.oldgl_fogenable = false;
3310 r_refdef.fog_density = 0;
3311 r_refdef.fog_red = 0;
3312 r_refdef.fog_green = 0;
3313 r_refdef.fog_blue = 0;
3314 r_refdef.fog_alpha = 0;
3315 r_refdef.fog_start = 0;
3316 r_refdef.fog_end = 0;
3320 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3321 r_refdef.fog_start = max(0, r_refdef.fog_start);
3322 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3324 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3326 if (r_refdef.fog_density)
3328 r_refdef.fogenabled = true;
3329 // this is the point where the fog reaches 0.9986 alpha, which we
3330 // consider a good enough cutoff point for the texture
3331 // (0.9986 * 256 == 255.6)
3332 if (r_fog_exp2.integer)
3333 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3335 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3336 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3337 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3338 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3339 // fog color was already set
3340 // update the fog texture
3341 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)
3342 R_BuildFogTexture();
3345 r_refdef.fogenabled = false;
3353 void R_RenderView(void)
3355 if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
3356 return; //Host_Error ("R_RenderView: NULL worldmodel");
3358 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3360 R_Shadow_UpdateWorldLightSelection();
3362 R_Bloom_StartFrame();
3363 R_Water_StartFrame();
3366 if (r_timereport_active)
3367 R_TimeReport("viewsetup");
3369 R_ResetViewRendering3D();
3371 if (r_refdef.view.clear || r_refdef.fogenabled)
3373 R_ClearScreen(r_refdef.fogenabled);
3374 if (r_timereport_active)
3375 R_TimeReport("viewclear");
3377 r_refdef.view.clear = true;
3379 r_refdef.view.showdebug = true;
3381 // this produces a bloom texture to be used in R_BlendView() later
3383 R_HDR_RenderBloomTexture();
3385 r_waterstate.numwaterplanes = 0;
3386 R_RenderScene(r_waterstate.enabled);
3389 if (r_timereport_active)
3390 R_TimeReport("blendview");
3392 GL_Scissor(0, 0, vid.width, vid.height);
3393 GL_ScissorTest(false);
3397 extern void R_DrawLightningBeams (void);
3398 extern void VM_CL_AddPolygonsToMeshQueue (void);
3399 extern void R_DrawPortals (void);
3400 extern cvar_t cl_locs_show;
3401 static void R_DrawLocs(void);
3402 static void R_DrawEntityBBoxes(void);
3403 void R_RenderScene(qboolean addwaterplanes)
3405 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3410 R_ResetViewRendering3D();
3413 if (r_timereport_active)
3414 R_TimeReport("watervis");
3416 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3418 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3419 if (r_timereport_active)
3420 R_TimeReport("waterworld");
3423 // don't let sound skip if going slow
3424 if (r_refdef.extraupdate)
3427 R_DrawModelsAddWaterPlanes();
3428 if (r_timereport_active)
3429 R_TimeReport("watermodels");
3431 R_Water_ProcessPlanes();
3432 if (r_timereport_active)
3433 R_TimeReport("waterscenes");
3436 R_ResetViewRendering3D();
3438 // don't let sound skip if going slow
3439 if (r_refdef.extraupdate)
3442 R_MeshQueue_BeginScene();
3447 if (r_timereport_active)
3448 R_TimeReport("visibility");
3450 Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
3452 if (cl.csqc_vidvars.drawworld)
3454 // don't let sound skip if going slow
3455 if (r_refdef.extraupdate)
3458 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3460 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3461 if (r_timereport_active)
3462 R_TimeReport("worldsky");
3465 if (R_DrawBrushModelsSky() && r_timereport_active)
3466 R_TimeReport("bmodelsky");
3469 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3471 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3472 if (r_timereport_active)
3473 R_TimeReport("worlddepth");
3475 if (r_depthfirst.integer >= 2)
3477 R_DrawModelsDepth();
3478 if (r_timereport_active)
3479 R_TimeReport("modeldepth");
3482 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3484 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3485 if (r_timereport_active)
3486 R_TimeReport("world");
3489 // don't let sound skip if going slow
3490 if (r_refdef.extraupdate)
3494 if (r_timereport_active)
3495 R_TimeReport("models");
3497 // don't let sound skip if going slow
3498 if (r_refdef.extraupdate)
3501 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3503 R_DrawModelShadows();
3505 R_ResetViewRendering3D();
3507 // don't let sound skip if going slow
3508 if (r_refdef.extraupdate)
3512 R_ShadowVolumeLighting(false);
3513 if (r_timereport_active)
3514 R_TimeReport("rtlights");
3516 // don't let sound skip if going slow
3517 if (r_refdef.extraupdate)
3520 if (cl.csqc_vidvars.drawworld)
3522 R_DrawLightningBeams();
3523 if (r_timereport_active)
3524 R_TimeReport("lightning");
3527 if (r_timereport_active)
3528 R_TimeReport("decals");
3531 if (r_timereport_active)
3532 R_TimeReport("particles");
3535 if (r_timereport_active)
3536 R_TimeReport("explosions");
3539 if (gl_support_fragment_shader)
3541 qglUseProgramObjectARB(0);CHECKGLERROR
3543 VM_CL_AddPolygonsToMeshQueue();
3545 if (r_refdef.view.showdebug)
3547 if (cl_locs_show.integer)
3550 if (r_timereport_active)
3551 R_TimeReport("showlocs");
3554 if (r_drawportals.integer)
3557 if (r_timereport_active)
3558 R_TimeReport("portals");
3561 if (r_showbboxes.value > 0)
3563 R_DrawEntityBBoxes();
3564 if (r_timereport_active)
3565 R_TimeReport("bboxes");
3569 if (gl_support_fragment_shader)
3571 qglUseProgramObjectARB(0);CHECKGLERROR
3573 R_MeshQueue_RenderTransparent();
3574 if (r_timereport_active)
3575 R_TimeReport("drawtrans");
3577 if (gl_support_fragment_shader)
3579 qglUseProgramObjectARB(0);CHECKGLERROR
3582 if (r_refdef.view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3584 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3585 if (r_timereport_active)
3586 R_TimeReport("worlddebug");
3587 R_DrawModelsDebug();
3588 if (r_timereport_active)
3589 R_TimeReport("modeldebug");
3592 if (gl_support_fragment_shader)
3594 qglUseProgramObjectARB(0);CHECKGLERROR
3597 if (cl.csqc_vidvars.drawworld)
3600 if (r_timereport_active)
3601 R_TimeReport("coronas");
3604 // don't let sound skip if going slow
3605 if (r_refdef.extraupdate)
3608 R_ResetViewRendering2D();
3611 static const int bboxelements[36] =
3621 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3624 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3625 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3626 GL_DepthMask(false);
3627 GL_DepthRange(0, 1);
3628 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3629 R_Mesh_Matrix(&identitymatrix);
3630 R_Mesh_ResetTextureState();
3632 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3633 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3634 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3635 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3636 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3637 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3638 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3639 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3640 R_FillColors(color4f, 8, cr, cg, cb, ca);
3641 if (r_refdef.fogenabled)
3643 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3645 f1 = FogPoint_World(v);
3647 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3648 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3649 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3652 R_Mesh_VertexPointer(vertex3f, 0, 0);
3653 R_Mesh_ColorPointer(color4f, 0, 0);
3654 R_Mesh_ResetTextureState();
3655 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3658 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3662 prvm_edict_t *edict;
3663 // this function draws bounding boxes of server entities
3667 for (i = 0;i < numsurfaces;i++)
3669 edict = PRVM_EDICT_NUM(surfacelist[i]);
3670 switch ((int)edict->fields.server->solid)
3672 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3673 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3674 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3675 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3676 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3677 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3679 color[3] *= r_showbboxes.value;
3680 color[3] = bound(0, color[3], 1);
3681 GL_DepthTest(!r_showdisabledepthtest.integer);
3682 GL_CullFace(r_refdef.view.cullface_front);
3683 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3688 static void R_DrawEntityBBoxes(void)
3691 prvm_edict_t *edict;
3693 // this function draws bounding boxes of server entities
3697 for (i = 0;i < prog->num_edicts;i++)
3699 edict = PRVM_EDICT_NUM(i);
3700 if (edict->priv.server->free)
3702 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3703 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3708 int nomodelelements[24] =
3720 float nomodelvertex3f[6*3] =
3730 float nomodelcolor4f[6*4] =
3732 0.0f, 0.0f, 0.5f, 1.0f,
3733 0.0f, 0.0f, 0.5f, 1.0f,
3734 0.0f, 0.5f, 0.0f, 1.0f,
3735 0.0f, 0.5f, 0.0f, 1.0f,
3736 0.5f, 0.0f, 0.0f, 1.0f,
3737 0.5f, 0.0f, 0.0f, 1.0f
3740 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3745 // this is only called once per entity so numsurfaces is always 1, and
3746 // surfacelist is always {0}, so this code does not handle batches
3747 R_Mesh_Matrix(&ent->matrix);
3749 if (ent->flags & EF_ADDITIVE)
3751 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3752 GL_DepthMask(false);
3754 else if (ent->alpha < 1)
3756 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3757 GL_DepthMask(false);
3761 GL_BlendFunc(GL_ONE, GL_ZERO);
3764 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3765 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3766 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3767 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
3768 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3769 if (r_refdef.fogenabled)
3772 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3773 R_Mesh_ColorPointer(color4f, 0, 0);
3774 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3775 f1 = FogPoint_World(org);
3777 for (i = 0, c = color4f;i < 6;i++, c += 4)
3779 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3780 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3781 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3785 else if (ent->alpha != 1)
3787 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3788 R_Mesh_ColorPointer(color4f, 0, 0);
3789 for (i = 0, c = color4f;i < 6;i++, c += 4)
3793 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3794 R_Mesh_ResetTextureState();
3795 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3798 void R_DrawNoModel(entity_render_t *ent)
3801 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3802 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3803 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3805 // R_DrawNoModelCallback(ent, 0);
3808 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3810 vec3_t right1, right2, diff, normal;
3812 VectorSubtract (org2, org1, normal);
3814 // calculate 'right' vector for start
3815 VectorSubtract (r_refdef.view.origin, org1, diff);
3816 CrossProduct (normal, diff, right1);
3817 VectorNormalize (right1);
3819 // calculate 'right' vector for end
3820 VectorSubtract (r_refdef.view.origin, org2, diff);
3821 CrossProduct (normal, diff, right2);
3822 VectorNormalize (right2);
3824 vert[ 0] = org1[0] + width * right1[0];
3825 vert[ 1] = org1[1] + width * right1[1];
3826 vert[ 2] = org1[2] + width * right1[2];
3827 vert[ 3] = org1[0] - width * right1[0];
3828 vert[ 4] = org1[1] - width * right1[1];
3829 vert[ 5] = org1[2] - width * right1[2];
3830 vert[ 6] = org2[0] - width * right2[0];
3831 vert[ 7] = org2[1] - width * right2[1];
3832 vert[ 8] = org2[2] - width * right2[2];
3833 vert[ 9] = org2[0] + width * right2[0];
3834 vert[10] = org2[1] + width * right2[1];
3835 vert[11] = org2[2] + width * right2[2];
3838 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3840 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)
3845 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
3846 fog = FogPoint_World(origin);
3848 R_Mesh_Matrix(&identitymatrix);
3849 GL_BlendFunc(blendfunc1, blendfunc2);
3855 GL_CullFace(r_refdef.view.cullface_front);
3858 GL_CullFace(r_refdef.view.cullface_back);
3860 GL_DepthMask(false);
3861 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3862 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3863 GL_DepthTest(!depthdisable);
3865 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3866 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3867 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3868 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3869 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3870 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3871 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3872 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3873 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3874 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3875 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3876 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3878 R_Mesh_VertexPointer(vertex3f, 0, 0);
3879 R_Mesh_ColorPointer(NULL, 0, 0);
3880 R_Mesh_ResetTextureState();
3881 R_Mesh_TexBind(0, R_GetTexture(texture));
3882 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3883 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
3884 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
3885 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3887 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3889 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3890 GL_BlendFunc(blendfunc1, GL_ONE);
3892 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
3893 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3897 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3902 VectorSet(v, x, y, z);
3903 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3904 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3906 if (i == mesh->numvertices)
3908 if (mesh->numvertices < mesh->maxvertices)
3910 VectorCopy(v, vertex3f);
3911 mesh->numvertices++;
3913 return mesh->numvertices;
3919 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3923 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3924 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3925 e = mesh->element3i + mesh->numtriangles * 3;
3926 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3928 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3929 if (mesh->numtriangles < mesh->maxtriangles)
3934 mesh->numtriangles++;
3936 element[1] = element[2];
3940 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3944 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3945 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3946 e = mesh->element3i + mesh->numtriangles * 3;
3947 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3949 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3950 if (mesh->numtriangles < mesh->maxtriangles)
3955 mesh->numtriangles++;
3957 element[1] = element[2];
3961 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3962 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3964 int planenum, planenum2;
3967 mplane_t *plane, *plane2;
3969 double temppoints[2][256*3];
3970 // figure out how large a bounding box we need to properly compute this brush
3972 for (w = 0;w < numplanes;w++)
3973 maxdist = max(maxdist, planes[w].dist);
3974 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3975 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3976 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3980 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3981 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3983 if (planenum2 == planenum)
3985 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);
3988 if (tempnumpoints < 3)
3990 // generate elements forming a triangle fan for this polygon
3991 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3995 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)
3997 texturelayer_t *layer;
3998 layer = t->currentlayers + t->currentnumlayers++;
4000 layer->depthmask = depthmask;
4001 layer->blendfunc1 = blendfunc1;
4002 layer->blendfunc2 = blendfunc2;
4003 layer->texture = texture;
4004 layer->texmatrix = *matrix;
4005 layer->color[0] = r * r_refdef.view.colorscale;
4006 layer->color[1] = g * r_refdef.view.colorscale;
4007 layer->color[2] = b * r_refdef.view.colorscale;
4008 layer->color[3] = a;
4011 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4014 index = parms[2] + r_refdef.time * parms[3];
4015 index -= floor(index);
4019 case Q3WAVEFUNC_NONE:
4020 case Q3WAVEFUNC_NOISE:
4021 case Q3WAVEFUNC_COUNT:
4024 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4025 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4026 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4027 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4028 case Q3WAVEFUNC_TRIANGLE:
4030 f = index - floor(index);
4041 return (float)(parms[0] + parms[1] * f);
4044 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4047 model_t *model = ent->model;
4050 q3shaderinfo_layer_tcmod_t *tcmod;
4052 // switch to an alternate material if this is a q1bsp animated material
4054 texture_t *texture = t;
4055 int s = ent->skinnum;
4056 if ((unsigned int)s >= (unsigned int)model->numskins)
4058 if (model->skinscenes)
4060 if (model->skinscenes[s].framecount > 1)
4061 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4063 s = model->skinscenes[s].firstframe;
4066 t = t + s * model->num_surfaces;
4069 // use an alternate animation if the entity's frame is not 0,
4070 // and only if the texture has an alternate animation
4071 if (ent->frame2 != 0 && t->anim_total[1])
4072 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
4074 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
4076 texture->currentframe = t;
4079 // update currentskinframe to be a qw skin or animation frame
4080 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4082 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4084 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4085 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4086 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);
4088 t->currentskinframe = r_qwskincache_skinframe[i];
4089 if (t->currentskinframe == NULL)
4090 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4092 else if (t->numskinframes >= 2)
4093 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4094 if (t->backgroundnumskinframes >= 2)
4095 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4097 t->currentmaterialflags = t->basematerialflags;
4098 t->currentalpha = ent->alpha;
4099 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4101 t->currentalpha *= r_wateralpha.value;
4103 * FIXME what is this supposed to do?
4104 // if rendering refraction/reflection, disable transparency
4105 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4106 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4109 if(!r_waterstate.enabled)
4110 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4111 if (!(ent->flags & RENDER_LIGHT))
4112 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4113 else if (rsurface.modeltexcoordlightmap2f == NULL)
4115 // pick a model lighting mode
4116 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4117 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4119 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4121 if (ent->effects & EF_ADDITIVE)
4122 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4123 else if (t->currentalpha < 1)
4124 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4125 if (ent->effects & EF_DOUBLESIDED)
4126 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4127 if (ent->effects & EF_NODEPTHTEST)
4128 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4129 if (ent->flags & RENDER_VIEWMODEL)
4130 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4131 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4132 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4134 // make sure that the waterscroll matrix is used on water surfaces when
4135 // there is no tcmod
4136 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4137 t->currenttexmatrix = r_waterscrollmatrix;
4139 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4142 switch(tcmod->tcmod)
4146 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4147 matrix = r_waterscrollmatrix;
4149 matrix = identitymatrix;
4151 case Q3TCMOD_ENTITYTRANSLATE:
4152 // this is used in Q3 to allow the gamecode to control texcoord
4153 // scrolling on the entity, which is not supported in darkplaces yet.
4154 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4156 case Q3TCMOD_ROTATE:
4157 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4158 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
4159 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4162 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4164 case Q3TCMOD_SCROLL:
4165 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
4167 case Q3TCMOD_STRETCH:
4168 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4169 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4171 case Q3TCMOD_TRANSFORM:
4172 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4173 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4174 VectorSet(tcmat + 6, 0 , 0 , 1);
4175 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4176 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4178 case Q3TCMOD_TURBULENT:
4179 // this is handled in the RSurf_PrepareVertices function
4180 matrix = identitymatrix;
4183 // either replace or concatenate the transformation
4185 t->currenttexmatrix = matrix;
4188 matrix4x4_t temp = t->currenttexmatrix;
4189 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4193 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4194 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4195 t->glosstexture = r_texture_black;
4196 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4197 t->backgroundglosstexture = r_texture_black;
4198 t->specularpower = r_shadow_glossexponent.value;
4199 // TODO: store reference values for these in the texture?
4200 t->specularscale = 0;
4201 if (r_shadow_gloss.integer > 0)
4203 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4205 if (r_shadow_glossintensity.value > 0)
4207 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4208 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4209 t->specularscale = r_shadow_glossintensity.value;
4212 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4214 t->glosstexture = r_texture_white;
4215 t->backgroundglosstexture = r_texture_white;
4216 t->specularscale = r_shadow_gloss2intensity.value;
4220 // lightmaps mode looks bad with dlights using actual texturing, so turn
4221 // off the colormap and glossmap, but leave the normalmap on as it still
4222 // accurately represents the shading involved
4223 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4225 t->basetexture = r_texture_white;
4226 t->specularscale = 0;
4229 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4230 VectorClear(t->dlightcolor);
4231 t->currentnumlayers = 0;
4232 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4234 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4236 int blendfunc1, blendfunc2, depthmask;
4237 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4239 blendfunc1 = GL_SRC_ALPHA;
4240 blendfunc2 = GL_ONE;
4242 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4244 blendfunc1 = GL_SRC_ALPHA;
4245 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4247 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4249 blendfunc1 = t->customblendfunc[0];
4250 blendfunc2 = t->customblendfunc[1];
4254 blendfunc1 = GL_ONE;
4255 blendfunc2 = GL_ZERO;
4257 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4258 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4260 rtexture_t *currentbasetexture;
4262 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4263 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4264 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4265 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4267 // fullbright is not affected by r_refdef.lightmapintensity
4268 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4269 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4270 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]);
4271 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4272 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]);
4276 vec3_t ambientcolor;
4278 // set the color tint used for lights affecting this surface
4279 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4281 // q3bsp has no lightmap updates, so the lightstylevalue that
4282 // would normally be baked into the lightmap must be
4283 // applied to the color
4284 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4285 if (ent->model->type == mod_brushq3)
4286 colorscale *= r_refdef.rtlightstylevalue[0];
4287 colorscale *= r_refdef.lightmapintensity;
4288 VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor);
4289 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4290 // basic lit geometry
4291 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4292 // add pants/shirt if needed
4293 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4294 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]);
4295 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4296 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]);
4297 // now add ambient passes if needed
4298 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4300 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
4301 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4302 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]);
4303 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4304 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]);
4307 if (t->currentskinframe->glow != NULL)
4308 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]);
4309 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4311 // if this is opaque use alpha blend which will darken the earlier
4314 // if this is an alpha blended material, all the earlier passes
4315 // were darkened by fog already, so we only need to add the fog
4316 // color ontop through the fog mask texture
4318 // if this is an additive blended material, all the earlier passes
4319 // were darkened by fog already, and we should not add fog color
4320 // (because the background was not darkened, there is no fog color
4321 // that was lost behind it).
4322 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]);
4329 void R_UpdateAllTextureInfo(entity_render_t *ent)
4333 for (i = 0;i < ent->model->num_texturesperskin;i++)
4334 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4337 rsurfacestate_t rsurface;
4339 void R_Mesh_ResizeArrays(int newvertices)
4342 if (rsurface.array_size >= newvertices)
4344 if (rsurface.array_modelvertex3f)
4345 Mem_Free(rsurface.array_modelvertex3f);
4346 rsurface.array_size = (newvertices + 1023) & ~1023;
4347 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4348 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4349 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4350 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4351 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4352 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4353 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4354 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4355 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4356 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4357 rsurface.array_color4f = base + rsurface.array_size * 27;
4358 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4361 void RSurf_CleanUp(void)
4364 if (rsurface.mode == RSURFMODE_GLSL)
4366 qglUseProgramObjectARB(0);CHECKGLERROR
4368 GL_AlphaTest(false);
4369 rsurface.mode = RSURFMODE_NONE;
4370 rsurface.uselightmaptexture = false;
4371 rsurface.texture = NULL;
4374 void RSurf_ActiveWorldEntity(void)
4376 model_t *model = r_refdef.worldmodel;
4378 if (rsurface.array_size < model->surfmesh.num_vertices)
4379 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4380 rsurface.matrix = identitymatrix;
4381 rsurface.inversematrix = identitymatrix;
4382 R_Mesh_Matrix(&identitymatrix);
4383 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4384 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4385 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4386 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4387 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4388 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4389 rsurface.frameblend[0].frame = 0;
4390 rsurface.frameblend[0].lerp = 1;
4391 rsurface.frameblend[1].frame = 0;
4392 rsurface.frameblend[1].lerp = 0;
4393 rsurface.frameblend[2].frame = 0;
4394 rsurface.frameblend[2].lerp = 0;
4395 rsurface.frameblend[3].frame = 0;
4396 rsurface.frameblend[3].lerp = 0;
4397 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4398 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4399 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4400 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4401 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4402 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4403 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4404 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4405 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4406 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4407 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4408 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4409 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4410 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4411 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4412 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4413 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4414 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4415 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4416 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4417 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4418 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4419 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4420 rsurface.modelelement3i = model->surfmesh.data_element3i;
4421 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4422 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4423 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4424 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4425 rsurface.modelsurfaces = model->data_surfaces;
4426 rsurface.generatedvertex = false;
4427 rsurface.vertex3f = rsurface.modelvertex3f;
4428 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4429 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4430 rsurface.svector3f = rsurface.modelsvector3f;
4431 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4432 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4433 rsurface.tvector3f = rsurface.modeltvector3f;
4434 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4435 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4436 rsurface.normal3f = rsurface.modelnormal3f;
4437 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4438 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4439 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4442 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4444 model_t *model = ent->model;
4446 if (rsurface.array_size < model->surfmesh.num_vertices)
4447 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4448 rsurface.matrix = ent->matrix;
4449 rsurface.inversematrix = ent->inversematrix;
4450 R_Mesh_Matrix(&rsurface.matrix);
4451 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
4452 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4453 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4454 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4455 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4456 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4457 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4458 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4459 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4460 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4461 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4462 rsurface.frameblend[0] = ent->frameblend[0];
4463 rsurface.frameblend[1] = ent->frameblend[1];
4464 rsurface.frameblend[2] = ent->frameblend[2];
4465 rsurface.frameblend[3] = ent->frameblend[3];
4466 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4467 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4468 if (ent->model->brush.submodel)
4470 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4471 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4473 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4477 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4478 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4479 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4480 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4481 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4483 else if (wantnormals)
4485 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4486 rsurface.modelsvector3f = NULL;
4487 rsurface.modeltvector3f = NULL;
4488 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4489 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4493 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4494 rsurface.modelsvector3f = NULL;
4495 rsurface.modeltvector3f = NULL;
4496 rsurface.modelnormal3f = NULL;
4497 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4499 rsurface.modelvertex3f_bufferobject = 0;
4500 rsurface.modelvertex3f_bufferoffset = 0;
4501 rsurface.modelsvector3f_bufferobject = 0;
4502 rsurface.modelsvector3f_bufferoffset = 0;
4503 rsurface.modeltvector3f_bufferobject = 0;
4504 rsurface.modeltvector3f_bufferoffset = 0;
4505 rsurface.modelnormal3f_bufferobject = 0;
4506 rsurface.modelnormal3f_bufferoffset = 0;
4507 rsurface.generatedvertex = true;
4511 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4512 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4513 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4514 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4515 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4516 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4517 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4518 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4519 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4520 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4521 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4522 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4523 rsurface.generatedvertex = false;
4525 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4526 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4527 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4528 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4529 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4530 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4531 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4532 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4533 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4534 rsurface.modelelement3i = model->surfmesh.data_element3i;
4535 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4536 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4537 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4538 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4539 rsurface.modelsurfaces = model->data_surfaces;
4540 rsurface.vertex3f = rsurface.modelvertex3f;
4541 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4542 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4543 rsurface.svector3f = rsurface.modelsvector3f;
4544 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4545 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4546 rsurface.tvector3f = rsurface.modeltvector3f;
4547 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4548 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4549 rsurface.normal3f = rsurface.modelnormal3f;
4550 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4551 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4552 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4555 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4556 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4559 int texturesurfaceindex;
4564 const float *v1, *in_tc;
4566 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4568 q3shaderinfo_deform_t *deform;
4569 // 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
4570 if (rsurface.generatedvertex)
4572 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4573 generatenormals = true;
4574 for (i = 0;i < Q3MAXDEFORMS;i++)
4576 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4578 generatetangents = true;
4579 generatenormals = true;
4581 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4582 generatenormals = true;
4584 if (generatenormals && !rsurface.modelnormal3f)
4586 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4587 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4588 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4589 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4591 if (generatetangents && !rsurface.modelsvector3f)
4593 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4594 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4595 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4596 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4597 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4598 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4599 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);
4602 rsurface.vertex3f = rsurface.modelvertex3f;
4603 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4604 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4605 rsurface.svector3f = rsurface.modelsvector3f;
4606 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4607 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4608 rsurface.tvector3f = rsurface.modeltvector3f;
4609 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4610 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4611 rsurface.normal3f = rsurface.modelnormal3f;
4612 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4613 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4614 // if vertices are deformed (sprite flares and things in maps, possibly
4615 // water waves, bulges and other deformations), generate them into
4616 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4617 // (may be static model data or generated data for an animated model, or
4618 // the previous deform pass)
4619 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4621 switch (deform->deform)
4624 case Q3DEFORM_PROJECTIONSHADOW:
4625 case Q3DEFORM_TEXT0:
4626 case Q3DEFORM_TEXT1:
4627 case Q3DEFORM_TEXT2:
4628 case Q3DEFORM_TEXT3:
4629 case Q3DEFORM_TEXT4:
4630 case Q3DEFORM_TEXT5:
4631 case Q3DEFORM_TEXT6:
4632 case Q3DEFORM_TEXT7:
4635 case Q3DEFORM_AUTOSPRITE:
4636 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4637 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4638 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4639 VectorNormalize(newforward);
4640 VectorNormalize(newright);
4641 VectorNormalize(newup);
4642 // make deformed versions of only the model vertices used by the specified surfaces
4643 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4645 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4646 // a single autosprite surface can contain multiple sprites...
4647 for (j = 0;j < surface->num_vertices - 3;j += 4)
4649 VectorClear(center);
4650 for (i = 0;i < 4;i++)
4651 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4652 VectorScale(center, 0.25f, center);
4653 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4654 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4655 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4656 for (i = 0;i < 4;i++)
4658 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4659 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4662 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);
4663 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);
4665 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4666 rsurface.vertex3f_bufferobject = 0;
4667 rsurface.vertex3f_bufferoffset = 0;
4668 rsurface.svector3f = rsurface.array_deformedsvector3f;
4669 rsurface.svector3f_bufferobject = 0;
4670 rsurface.svector3f_bufferoffset = 0;
4671 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4672 rsurface.tvector3f_bufferobject = 0;
4673 rsurface.tvector3f_bufferoffset = 0;
4674 rsurface.normal3f = rsurface.array_deformednormal3f;
4675 rsurface.normal3f_bufferobject = 0;
4676 rsurface.normal3f_bufferoffset = 0;
4678 case Q3DEFORM_AUTOSPRITE2:
4679 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4680 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4681 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4682 VectorNormalize(newforward);
4683 VectorNormalize(newright);
4684 VectorNormalize(newup);
4685 // make deformed versions of only the model vertices used by the specified surfaces
4686 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4688 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4689 const float *v1, *v2;
4699 memset(shortest, 0, sizeof(shortest));
4700 // a single autosprite surface can contain multiple sprites...
4701 for (j = 0;j < surface->num_vertices - 3;j += 4)
4703 VectorClear(center);
4704 for (i = 0;i < 4;i++)
4705 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4706 VectorScale(center, 0.25f, center);
4707 // find the two shortest edges, then use them to define the
4708 // axis vectors for rotating around the central axis
4709 for (i = 0;i < 6;i++)
4711 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4712 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4714 Debug_PolygonBegin(NULL, 0, false, 0);
4715 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4716 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);
4717 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4720 l = VectorDistance2(v1, v2);
4721 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4723 l += (1.0f / 1024.0f);
4724 if (shortest[0].length2 > l || i == 0)
4726 shortest[1] = shortest[0];
4727 shortest[0].length2 = l;
4728 shortest[0].v1 = v1;
4729 shortest[0].v2 = v2;
4731 else if (shortest[1].length2 > l || i == 1)
4733 shortest[1].length2 = l;
4734 shortest[1].v1 = v1;
4735 shortest[1].v2 = v2;
4738 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4739 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4741 Debug_PolygonBegin(NULL, 0, false, 0);
4742 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4743 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);
4744 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4747 // this calculates the right vector from the shortest edge
4748 // and the up vector from the edge midpoints
4749 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4750 VectorNormalize(right);
4751 VectorSubtract(end, start, up);
4752 VectorNormalize(up);
4753 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4754 //VectorSubtract(rsurface.modelorg, center, forward);
4755 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
4756 VectorNegate(forward, forward);
4757 VectorReflect(forward, 0, up, forward);
4758 VectorNormalize(forward);
4759 CrossProduct(up, forward, newright);
4760 VectorNormalize(newright);
4762 Debug_PolygonBegin(NULL, 0, false, 0);
4763 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);
4764 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4765 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4769 Debug_PolygonBegin(NULL, 0, false, 0);
4770 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4771 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4772 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4775 // rotate the quad around the up axis vector, this is made
4776 // especially easy by the fact we know the quad is flat,
4777 // so we only have to subtract the center position and
4778 // measure distance along the right vector, and then
4779 // multiply that by the newright vector and add back the
4781 // we also need to subtract the old position to undo the
4782 // displacement from the center, which we do with a
4783 // DotProduct, the subtraction/addition of center is also
4784 // optimized into DotProducts here
4785 l = DotProduct(right, center);
4786 for (i = 0;i < 4;i++)
4788 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4789 f = DotProduct(right, v1) - l;
4790 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4793 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);
4794 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);
4796 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4797 rsurface.vertex3f_bufferobject = 0;
4798 rsurface.vertex3f_bufferoffset = 0;
4799 rsurface.svector3f = rsurface.array_deformedsvector3f;
4800 rsurface.svector3f_bufferobject = 0;
4801 rsurface.svector3f_bufferoffset = 0;
4802 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4803 rsurface.tvector3f_bufferobject = 0;
4804 rsurface.tvector3f_bufferoffset = 0;
4805 rsurface.normal3f = rsurface.array_deformednormal3f;
4806 rsurface.normal3f_bufferobject = 0;
4807 rsurface.normal3f_bufferoffset = 0;
4809 case Q3DEFORM_NORMAL:
4810 // deform the normals to make reflections wavey
4811 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4813 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4814 for (j = 0;j < surface->num_vertices;j++)
4817 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4818 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4819 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4820 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4821 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4822 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4823 VectorNormalize(normal);
4825 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);
4827 rsurface.svector3f = rsurface.array_deformedsvector3f;
4828 rsurface.svector3f_bufferobject = 0;
4829 rsurface.svector3f_bufferoffset = 0;
4830 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4831 rsurface.tvector3f_bufferobject = 0;
4832 rsurface.tvector3f_bufferoffset = 0;
4833 rsurface.normal3f = rsurface.array_deformednormal3f;
4834 rsurface.normal3f_bufferobject = 0;
4835 rsurface.normal3f_bufferoffset = 0;
4838 // deform vertex array to make wavey water and flags and such
4839 waveparms[0] = deform->waveparms[0];
4840 waveparms[1] = deform->waveparms[1];
4841 waveparms[2] = deform->waveparms[2];
4842 waveparms[3] = deform->waveparms[3];
4843 // this is how a divisor of vertex influence on deformation
4844 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4845 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4846 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4848 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4849 for (j = 0;j < surface->num_vertices;j++)
4851 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4852 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4853 // if the wavefunc depends on time, evaluate it per-vertex
4856 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4857 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4859 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4862 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4863 rsurface.vertex3f_bufferobject = 0;
4864 rsurface.vertex3f_bufferoffset = 0;
4866 case Q3DEFORM_BULGE:
4867 // deform vertex array to make the surface have moving bulges
4868 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4870 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4871 for (j = 0;j < surface->num_vertices;j++)
4873 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4874 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4877 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4878 rsurface.vertex3f_bufferobject = 0;
4879 rsurface.vertex3f_bufferoffset = 0;
4882 // deform vertex array
4883 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4884 VectorScale(deform->parms, scale, waveparms);
4885 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4887 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4888 for (j = 0;j < surface->num_vertices;j++)
4889 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4891 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4892 rsurface.vertex3f_bufferobject = 0;
4893 rsurface.vertex3f_bufferoffset = 0;
4897 // generate texcoords based on the chosen texcoord source
4898 switch(rsurface.texture->tcgen.tcgen)
4901 case Q3TCGEN_TEXTURE:
4902 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4903 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4904 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4906 case Q3TCGEN_LIGHTMAP:
4907 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4908 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4909 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4911 case Q3TCGEN_VECTOR:
4912 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4914 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4915 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)
4917 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4918 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4921 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4922 rsurface.texcoordtexture2f_bufferobject = 0;
4923 rsurface.texcoordtexture2f_bufferoffset = 0;
4925 case Q3TCGEN_ENVIRONMENT:
4926 // make environment reflections using a spheremap
4927 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4929 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4930 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4931 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4932 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4933 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4935 float l, d, eyedir[3];
4936 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4937 l = 0.5f / VectorLength(eyedir);
4938 d = DotProduct(normal, eyedir)*2;
4939 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4940 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4943 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4944 rsurface.texcoordtexture2f_bufferobject = 0;
4945 rsurface.texcoordtexture2f_bufferoffset = 0;
4948 // the only tcmod that needs software vertex processing is turbulent, so
4949 // check for it here and apply the changes if needed
4950 // and we only support that as the first one
4951 // (handling a mixture of turbulent and other tcmods would be problematic
4952 // without punting it entirely to a software path)
4953 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4955 amplitude = rsurface.texture->tcmods[0].parms[1];
4956 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4957 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4959 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4960 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)
4962 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4963 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4966 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4967 rsurface.texcoordtexture2f_bufferobject = 0;
4968 rsurface.texcoordtexture2f_bufferoffset = 0;
4970 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4971 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4972 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4973 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4976 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4979 const msurface_t *surface = texturesurfacelist[0];
4980 const msurface_t *surface2;
4985 // TODO: lock all array ranges before render, rather than on each surface
4986 if (texturenumsurfaces == 1)
4988 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4989 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));
4991 else if (r_batchmode.integer == 2)
4993 #define MAXBATCHTRIANGLES 4096
4994 int batchtriangles = 0;
4995 int batchelements[MAXBATCHTRIANGLES*3];
4996 for (i = 0;i < texturenumsurfaces;i = j)
4998 surface = texturesurfacelist[i];
5000 if (surface->num_triangles > MAXBATCHTRIANGLES)
5002 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));
5005 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5006 batchtriangles = surface->num_triangles;
5007 firstvertex = surface->num_firstvertex;
5008 endvertex = surface->num_firstvertex + surface->num_vertices;
5009 for (;j < texturenumsurfaces;j++)
5011 surface2 = texturesurfacelist[j];
5012 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5014 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5015 batchtriangles += surface2->num_triangles;
5016 firstvertex = min(firstvertex, surface2->num_firstvertex);
5017 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5019 surface2 = texturesurfacelist[j-1];
5020 numvertices = endvertex - firstvertex;
5021 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5024 else if (r_batchmode.integer == 1)
5026 for (i = 0;i < texturenumsurfaces;i = j)
5028 surface = texturesurfacelist[i];
5029 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5030 if (texturesurfacelist[j] != surface2)
5032 surface2 = texturesurfacelist[j-1];
5033 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5034 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5035 GL_LockArrays(surface->num_firstvertex, numvertices);
5036 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5041 for (i = 0;i < texturenumsurfaces;i++)
5043 surface = texturesurfacelist[i];
5044 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5045 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));
5050 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5052 int i, planeindex, vertexindex;
5056 r_waterstate_waterplane_t *p, *bestp;
5057 msurface_t *surface;
5058 if (r_waterstate.renderingscene)
5060 for (i = 0;i < texturenumsurfaces;i++)
5062 surface = texturesurfacelist[i];
5063 if (lightmaptexunit >= 0)
5064 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5065 if (deluxemaptexunit >= 0)
5066 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5067 // pick the closest matching water plane
5070 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5073 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5075 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5076 d += fabs(PlaneDiff(vert, &p->plane));
5078 if (bestd > d || !bestp)
5086 if (refractiontexunit >= 0)
5087 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5088 if (reflectiontexunit >= 0)
5089 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5093 if (refractiontexunit >= 0)
5094 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5095 if (reflectiontexunit >= 0)
5096 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5098 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5099 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));
5103 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5107 const msurface_t *surface = texturesurfacelist[0];
5108 const msurface_t *surface2;
5113 // TODO: lock all array ranges before render, rather than on each surface
5114 if (texturenumsurfaces == 1)
5116 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5117 if (deluxemaptexunit >= 0)
5118 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5119 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5120 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));
5122 else if (r_batchmode.integer == 2)
5124 #define MAXBATCHTRIANGLES 4096
5125 int batchtriangles = 0;
5126 int batchelements[MAXBATCHTRIANGLES*3];
5127 for (i = 0;i < texturenumsurfaces;i = j)
5129 surface = texturesurfacelist[i];
5130 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5131 if (deluxemaptexunit >= 0)
5132 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5134 if (surface->num_triangles > MAXBATCHTRIANGLES)
5136 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));
5139 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5140 batchtriangles = surface->num_triangles;
5141 firstvertex = surface->num_firstvertex;
5142 endvertex = surface->num_firstvertex + surface->num_vertices;
5143 for (;j < texturenumsurfaces;j++)
5145 surface2 = texturesurfacelist[j];
5146 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5148 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5149 batchtriangles += surface2->num_triangles;
5150 firstvertex = min(firstvertex, surface2->num_firstvertex);
5151 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5153 surface2 = texturesurfacelist[j-1];
5154 numvertices = endvertex - firstvertex;
5155 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5158 else if (r_batchmode.integer == 1)
5161 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5162 for (i = 0;i < texturenumsurfaces;i = j)
5164 surface = texturesurfacelist[i];
5165 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5166 if (texturesurfacelist[j] != surface2)
5168 Con_Printf(" %i", j - i);
5171 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5173 for (i = 0;i < texturenumsurfaces;i = j)
5175 surface = texturesurfacelist[i];
5176 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5177 if (deluxemaptexunit >= 0)
5178 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5179 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5180 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5183 Con_Printf(" %i", j - i);
5185 surface2 = texturesurfacelist[j-1];
5186 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5187 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5188 GL_LockArrays(surface->num_firstvertex, numvertices);
5189 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5197 for (i = 0;i < texturenumsurfaces;i++)
5199 surface = texturesurfacelist[i];
5200 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5201 if (deluxemaptexunit >= 0)
5202 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5203 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5204 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));
5209 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5212 int texturesurfaceindex;
5213 if (r_showsurfaces.integer == 2)
5215 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5217 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5218 for (j = 0;j < surface->num_triangles;j++)
5220 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5221 GL_Color(f, f, f, 1);
5222 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)));
5228 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5230 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5231 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5232 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);
5233 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5234 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));
5239 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5241 int texturesurfaceindex;
5245 if (rsurface.lightmapcolor4f)
5247 // generate color arrays for the surfaces in this list
5248 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5250 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5251 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)
5253 f = FogPoint_Model(v);
5263 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5265 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5266 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)
5268 f = FogPoint_Model(v);
5276 rsurface.lightmapcolor4f = rsurface.array_color4f;
5277 rsurface.lightmapcolor4f_bufferobject = 0;
5278 rsurface.lightmapcolor4f_bufferoffset = 0;
5281 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5283 int texturesurfaceindex;
5286 if (!rsurface.lightmapcolor4f)
5288 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5290 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5291 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)
5299 rsurface.lightmapcolor4f = rsurface.array_color4f;
5300 rsurface.lightmapcolor4f_bufferobject = 0;
5301 rsurface.lightmapcolor4f_bufferoffset = 0;
5304 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5307 rsurface.lightmapcolor4f = NULL;
5308 rsurface.lightmapcolor4f_bufferobject = 0;
5309 rsurface.lightmapcolor4f_bufferoffset = 0;
5310 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5311 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5312 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5313 GL_Color(r, g, b, a);
5314 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5317 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5319 // TODO: optimize applyfog && applycolor case
5320 // just apply fog if necessary, and tint the fog color array if necessary
5321 rsurface.lightmapcolor4f = NULL;
5322 rsurface.lightmapcolor4f_bufferobject = 0;
5323 rsurface.lightmapcolor4f_bufferoffset = 0;
5324 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5325 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5326 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5327 GL_Color(r, g, b, a);
5328 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5331 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5333 int texturesurfaceindex;
5337 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5339 // generate color arrays for the surfaces in this list
5340 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5342 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5343 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5345 if (surface->lightmapinfo->samples)
5347 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5348 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5349 VectorScale(lm, scale, c);
5350 if (surface->lightmapinfo->styles[1] != 255)
5352 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5354 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5355 VectorMA(c, scale, lm, c);
5356 if (surface->lightmapinfo->styles[2] != 255)
5359 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5360 VectorMA(c, scale, lm, c);
5361 if (surface->lightmapinfo->styles[3] != 255)
5364 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5365 VectorMA(c, scale, lm, c);
5375 rsurface.lightmapcolor4f = rsurface.array_color4f;
5376 rsurface.lightmapcolor4f_bufferobject = 0;
5377 rsurface.lightmapcolor4f_bufferoffset = 0;
5381 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5382 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5383 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5385 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5386 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5387 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5388 GL_Color(r, g, b, a);
5389 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5392 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5394 int texturesurfaceindex;
5398 vec3_t ambientcolor;
5399 vec3_t diffusecolor;
5403 VectorCopy(rsurface.modellight_lightdir, lightdir);
5404 f = 0.5f * r_refdef.lightmapintensity;
5405 ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5406 ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5407 ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5408 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5409 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5410 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5411 if (VectorLength2(diffusecolor) > 0)
5413 // generate color arrays for the surfaces in this list
5414 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5416 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5417 int numverts = surface->num_vertices;
5418 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5419 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5420 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5421 // q3-style directional shading
5422 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5424 if ((f = DotProduct(c2, lightdir)) > 0)
5425 VectorMA(ambientcolor, f, diffusecolor, c);
5427 VectorCopy(ambientcolor, c);
5436 rsurface.lightmapcolor4f = rsurface.array_color4f;
5437 rsurface.lightmapcolor4f_bufferobject = 0;
5438 rsurface.lightmapcolor4f_bufferoffset = 0;
5442 r = ambientcolor[0];
5443 g = ambientcolor[1];
5444 b = ambientcolor[2];
5445 rsurface.lightmapcolor4f = NULL;
5446 rsurface.lightmapcolor4f_bufferobject = 0;
5447 rsurface.lightmapcolor4f_bufferoffset = 0;
5449 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5450 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5451 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5452 GL_Color(r, g, b, a);
5453 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5456 void RSurf_SetupDepthAndCulling(void)
5458 // submodels are biased to avoid z-fighting with world surfaces that they
5459 // may be exactly overlapping (avoids z-fighting artifacts on certain
5460 // doors and things in Quake maps)
5461 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5462 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5463 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5464 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
5467 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5469 RSurf_SetupDepthAndCulling();
5470 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5472 rsurface.mode = RSURFMODE_SHOWSURFACES;
5474 GL_BlendFunc(GL_ONE, GL_ZERO);
5475 R_Mesh_ColorPointer(NULL, 0, 0);
5476 R_Mesh_ResetTextureState();
5478 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5479 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5482 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5484 // transparent sky would be ridiculous
5485 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5487 if (rsurface.mode != RSURFMODE_SKY)
5489 if (rsurface.mode == RSURFMODE_GLSL)
5491 qglUseProgramObjectARB(0);CHECKGLERROR
5493 rsurface.mode = RSURFMODE_SKY;
5497 skyrendernow = false;
5499 // restore entity matrix
5500 R_Mesh_Matrix(&rsurface.matrix);
5502 RSurf_SetupDepthAndCulling();
5504 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5505 // skymasking on them, and Quake3 never did sky masking (unlike
5506 // software Quake and software Quake2), so disable the sky masking
5507 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5508 // and skymasking also looks very bad when noclipping outside the
5509 // level, so don't use it then either.
5510 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
5512 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5513 R_Mesh_ColorPointer(NULL, 0, 0);
5514 R_Mesh_ResetTextureState();
5515 if (skyrendermasked)
5517 // depth-only (masking)
5518 GL_ColorMask(0,0,0,0);
5519 // just to make sure that braindead drivers don't draw
5520 // anything despite that colormask...
5521 GL_BlendFunc(GL_ZERO, GL_ONE);
5526 GL_BlendFunc(GL_ONE, GL_ZERO);
5528 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5529 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5530 if (skyrendermasked)
5531 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5535 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5537 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5540 if (rsurface.mode != RSURFMODE_GLSL)
5542 rsurface.mode = RSURFMODE_GLSL;
5543 R_Mesh_ResetTextureState();
5544 GL_Color(1, 1, 1, 1);
5547 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5548 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5549 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5550 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5551 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5552 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5553 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5554 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5556 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5557 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5558 R_Mesh_ColorPointer(NULL, 0, 0);
5560 else if (rsurface.uselightmaptexture)
5562 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5563 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5564 R_Mesh_ColorPointer(NULL, 0, 0);
5568 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5569 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5570 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5572 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5573 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5574 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5576 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5578 // render background
5579 GL_BlendFunc(GL_ONE, GL_ZERO);
5581 GL_AlphaTest(false);
5583 GL_Color(1, 1, 1, 1);
5584 R_Mesh_ColorPointer(NULL, 0, 0);
5586 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5587 if (r_glsl_permutation)
5589 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5590 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5591 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5592 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5593 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5594 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5595 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5598 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5599 GL_DepthMask(false);
5600 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5601 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5603 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5604 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5605 R_Mesh_ColorPointer(NULL, 0, 0);
5607 else if (rsurface.uselightmaptexture)
5609 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5610 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5611 R_Mesh_ColorPointer(NULL, 0, 0);
5615 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5616 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5617 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5619 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5620 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5623 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5624 if (!r_glsl_permutation)
5627 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5628 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5629 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5630 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5631 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5632 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5634 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5636 GL_BlendFunc(GL_ONE, GL_ZERO);
5638 GL_AlphaTest(false);
5641 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5643 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5644 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);
5646 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5650 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5651 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);
5653 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5655 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5660 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5662 // OpenGL 1.3 path - anything not completely ancient
5663 int texturesurfaceindex;
5664 qboolean applycolor;
5668 const texturelayer_t *layer;
5669 if (rsurface.mode != RSURFMODE_MULTIPASS)
5670 rsurface.mode = RSURFMODE_MULTIPASS;
5671 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5673 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5676 int layertexrgbscale;
5677 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5679 if (layerindex == 0)
5683 GL_AlphaTest(false);
5684 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5687 GL_DepthMask(layer->depthmask);
5688 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5689 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
5691 layertexrgbscale = 4;
5692 VectorScale(layer->color, 0.25f, layercolor);
5694 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
5696 layertexrgbscale = 2;
5697 VectorScale(layer->color, 0.5f, layercolor);
5701 layertexrgbscale = 1;
5702 VectorScale(layer->color, 1.0f, layercolor);
5704 layercolor[3] = layer->color[3];
5705 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5706 R_Mesh_ColorPointer(NULL, 0, 0);
5707 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5708 switch (layer->type)
5710 case TEXTURELAYERTYPE_LITTEXTURE:
5711 memset(&m, 0, sizeof(m));
5712 m.tex[0] = R_GetTexture(r_texture_white);
5713 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5714 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5715 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5716 m.tex[1] = R_GetTexture(layer->texture);
5717 m.texmatrix[1] = layer->texmatrix;
5718 m.texrgbscale[1] = layertexrgbscale;
5719 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5720 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5721 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5722 R_Mesh_TextureState(&m);
5723 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5724 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5725 else if (rsurface.uselightmaptexture)
5726 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5728 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5730 case TEXTURELAYERTYPE_TEXTURE:
5731 memset(&m, 0, sizeof(m));
5732 m.tex[0] = R_GetTexture(layer->texture);
5733 m.texmatrix[0] = layer->texmatrix;
5734 m.texrgbscale[0] = layertexrgbscale;
5735 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5736 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5737 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5738 R_Mesh_TextureState(&m);
5739 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5741 case TEXTURELAYERTYPE_FOG:
5742 memset(&m, 0, sizeof(m));
5743 m.texrgbscale[0] = layertexrgbscale;
5746 m.tex[0] = R_GetTexture(layer->texture);
5747 m.texmatrix[0] = layer->texmatrix;
5748 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5749 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5750 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5752 R_Mesh_TextureState(&m);
5753 // generate a color array for the fog pass
5754 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5755 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5759 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5760 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)
5762 f = 1 - FogPoint_Model(v);
5763 c[0] = layercolor[0];
5764 c[1] = layercolor[1];
5765 c[2] = layercolor[2];
5766 c[3] = f * layercolor[3];
5769 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5772 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5774 GL_LockArrays(0, 0);
5777 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5779 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5780 GL_AlphaTest(false);
5784 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5786 // OpenGL 1.1 - crusty old voodoo path
5787 int texturesurfaceindex;
5791 const texturelayer_t *layer;
5792 if (rsurface.mode != RSURFMODE_MULTIPASS)
5793 rsurface.mode = RSURFMODE_MULTIPASS;
5794 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5796 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5798 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5800 if (layerindex == 0)
5804 GL_AlphaTest(false);
5805 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5808 GL_DepthMask(layer->depthmask);
5809 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5810 R_Mesh_ColorPointer(NULL, 0, 0);
5811 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5812 switch (layer->type)
5814 case TEXTURELAYERTYPE_LITTEXTURE:
5815 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5817 // two-pass lit texture with 2x rgbscale
5818 // first the lightmap pass
5819 memset(&m, 0, sizeof(m));
5820 m.tex[0] = R_GetTexture(r_texture_white);
5821 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5822 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5823 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5824 R_Mesh_TextureState(&m);
5825 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5826 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5827 else if (rsurface.uselightmaptexture)
5828 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5830 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5831 GL_LockArrays(0, 0);
5832 // then apply the texture to it
5833 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5834 memset(&m, 0, sizeof(m));
5835 m.tex[0] = R_GetTexture(layer->texture);
5836 m.texmatrix[0] = layer->texmatrix;
5837 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5838 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5839 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5840 R_Mesh_TextureState(&m);
5841 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);
5845 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5846 memset(&m, 0, sizeof(m));
5847 m.tex[0] = R_GetTexture(layer->texture);
5848 m.texmatrix[0] = layer->texmatrix;
5849 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5850 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5851 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5852 R_Mesh_TextureState(&m);
5853 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5854 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);
5856 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);
5859 case TEXTURELAYERTYPE_TEXTURE:
5860 // singletexture unlit texture with transparency support
5861 memset(&m, 0, sizeof(m));
5862 m.tex[0] = R_GetTexture(layer->texture);
5863 m.texmatrix[0] = layer->texmatrix;
5864 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5865 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5866 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5867 R_Mesh_TextureState(&m);
5868 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);
5870 case TEXTURELAYERTYPE_FOG:
5871 // singletexture fogging
5872 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5875 memset(&m, 0, sizeof(m));
5876 m.tex[0] = R_GetTexture(layer->texture);
5877 m.texmatrix[0] = layer->texmatrix;
5878 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5879 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5880 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5881 R_Mesh_TextureState(&m);
5884 R_Mesh_ResetTextureState();
5885 // generate a color array for the fog pass
5886 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5890 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5891 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)
5893 f = 1 - FogPoint_Model(v);
5894 c[0] = layer->color[0];
5895 c[1] = layer->color[1];
5896 c[2] = layer->color[2];
5897 c[3] = f * layer->color[3];
5900 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5903 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5905 GL_LockArrays(0, 0);
5908 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5910 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5911 GL_AlphaTest(false);
5915 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5917 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5919 rsurface.rtlight = NULL;
5923 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5925 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5927 if (rsurface.mode != RSURFMODE_MULTIPASS)
5928 rsurface.mode = RSURFMODE_MULTIPASS;
5929 if (r_depthfirst.integer == 3)
5931 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5932 if (!r_refdef.view.showdebug)
5933 GL_Color(0, 0, 0, 1);
5935 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5939 GL_ColorMask(0,0,0,0);
5942 RSurf_SetupDepthAndCulling();
5944 GL_BlendFunc(GL_ONE, GL_ZERO);
5946 GL_AlphaTest(false);
5947 R_Mesh_ColorPointer(NULL, 0, 0);
5948 R_Mesh_ResetTextureState();
5949 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5950 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5951 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5953 else if (r_depthfirst.integer == 3)
5955 else if (!r_refdef.view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5957 GL_Color(0, 0, 0, 1);
5958 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5960 else if (r_showsurfaces.integer)
5962 if (rsurface.mode != RSURFMODE_MULTIPASS)
5963 rsurface.mode = RSURFMODE_MULTIPASS;
5964 RSurf_SetupDepthAndCulling();
5966 GL_BlendFunc(GL_ONE, GL_ZERO);
5967 GL_DepthMask(writedepth);
5969 GL_AlphaTest(false);
5970 R_Mesh_ColorPointer(NULL, 0, 0);
5971 R_Mesh_ResetTextureState();
5972 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5973 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5975 else if (gl_lightmaps.integer)
5978 if (rsurface.mode != RSURFMODE_MULTIPASS)
5979 rsurface.mode = RSURFMODE_MULTIPASS;
5980 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5982 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
5983 GL_BlendFunc(GL_ONE, GL_ZERO);
5984 GL_DepthMask(writedepth);
5986 GL_AlphaTest(false);
5987 R_Mesh_ColorPointer(NULL, 0, 0);
5988 memset(&m, 0, sizeof(m));
5989 m.tex[0] = R_GetTexture(r_texture_white);
5990 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5991 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5992 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5993 R_Mesh_TextureState(&m);
5994 RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist);
5995 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5996 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5997 else if (rsurface.uselightmaptexture)
5998 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6000 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6002 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6003 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6004 else if (rsurface.texture->currentnumlayers)
6006 // write depth for anything we skipped on the depth-only pass earlier
6007 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6009 RSurf_SetupDepthAndCulling();
6010 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6011 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6012 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6013 if (r_glsl.integer && gl_support_fragment_shader)
6014 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
6015 else if (gl_combine.integer && r_textureunits.integer >= 2)
6016 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
6018 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
6021 GL_LockArrays(0, 0);
6024 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6027 int texturenumsurfaces, endsurface;
6029 msurface_t *surface;
6030 msurface_t *texturesurfacelist[1024];
6032 // if the model is static it doesn't matter what value we give for
6033 // wantnormals and wanttangents, so this logic uses only rules applicable
6034 // to a model, knowing that they are meaningless otherwise
6035 if (ent == r_refdef.worldentity)
6036 RSurf_ActiveWorldEntity();
6037 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6038 RSurf_ActiveModelEntity(ent, false, false);
6040 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6042 for (i = 0;i < numsurfaces;i = j)
6045 surface = rsurface.modelsurfaces + surfacelist[i];
6046 texture = surface->texture;
6047 R_UpdateTextureInfo(ent, texture);
6048 rsurface.texture = texture->currentframe;
6049 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6050 // scan ahead until we find a different texture
6051 endsurface = min(i + 1024, numsurfaces);
6052 texturenumsurfaces = 0;
6053 texturesurfacelist[texturenumsurfaces++] = surface;
6054 for (;j < endsurface;j++)
6056 surface = rsurface.modelsurfaces + surfacelist[j];
6057 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6059 texturesurfacelist[texturenumsurfaces++] = surface;
6061 // render the range of surfaces
6062 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
6068 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6071 vec3_t tempcenter, center;
6073 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6076 for (i = 0;i < numsurfaces;i++)
6077 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6078 R_Water_AddWaterPlane(surfacelist[i]);
6081 // break the surface list down into batches by texture and use of lightmapping
6082 for (i = 0;i < numsurfaces;i = j)
6085 // texture is the base texture pointer, rsurface.texture is the
6086 // current frame/skin the texture is directing us to use (for example
6087 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6088 // use skin 1 instead)
6089 texture = surfacelist[i]->texture;
6090 rsurface.texture = texture->currentframe;
6091 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6092 if (!(rsurface.texture->currentmaterialflags & flagsmask))
6094 // if this texture is not the kind we want, skip ahead to the next one
6095 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6099 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6101 // transparent surfaces get pushed off into the transparent queue
6102 const msurface_t *surface = surfacelist[i];
6105 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6106 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6107 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6108 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6109 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
6113 // simply scan ahead until we find a different texture or lightmap state
6114 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6116 // render the range of surfaces
6117 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6122 float locboxvertex3f[6*4*3] =
6124 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6125 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6126 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6127 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6128 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6129 1,0,0, 0,0,0, 0,1,0, 1,1,0
6132 int locboxelement3i[6*2*3] =
6142 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6145 cl_locnode_t *loc = (cl_locnode_t *)ent;
6147 float vertex3f[6*4*3];
6149 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6150 GL_DepthMask(false);
6151 GL_DepthRange(0, 1);
6152 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6154 GL_CullFace(GL_NONE);
6155 R_Mesh_Matrix(&identitymatrix);
6157 R_Mesh_VertexPointer(vertex3f, 0, 0);
6158 R_Mesh_ColorPointer(NULL, 0, 0);
6159 R_Mesh_ResetTextureState();
6162 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6163 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6164 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6165 surfacelist[0] < 0 ? 0.5f : 0.125f);
6167 if (VectorCompare(loc->mins, loc->maxs))
6169 VectorSet(size, 2, 2, 2);
6170 VectorMA(loc->mins, -0.5f, size, mins);
6174 VectorCopy(loc->mins, mins);
6175 VectorSubtract(loc->maxs, loc->mins, size);
6178 for (i = 0;i < 6*4*3;)
6179 for (j = 0;j < 3;j++, i++)
6180 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6182 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6185 void R_DrawLocs(void)
6188 cl_locnode_t *loc, *nearestloc;
6190 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6191 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6193 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6194 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6198 void R_DrawDebugModel(entity_render_t *ent)
6200 int i, j, k, l, flagsmask;
6201 const int *elements;
6203 msurface_t *surface;
6204 model_t *model = ent->model;
6207 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6209 R_Mesh_ColorPointer(NULL, 0, 0);
6210 R_Mesh_ResetTextureState();
6211 GL_DepthRange(0, 1);
6212 GL_DepthTest(!r_showdisabledepthtest.integer);
6213 GL_DepthMask(false);
6214 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6216 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6218 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6219 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6221 if (brush->colbrushf && brush->colbrushf->numtriangles)
6223 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6224 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);
6225 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6228 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6230 if (surface->num_collisiontriangles)
6232 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6233 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);
6234 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6239 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6241 if (r_showtris.integer || r_shownormals.integer)
6243 if (r_showdisabledepthtest.integer)
6245 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6246 GL_DepthMask(false);
6250 GL_BlendFunc(GL_ONE, GL_ZERO);
6253 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6255 if (ent == r_refdef.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
6257 rsurface.texture = surface->texture->currentframe;
6258 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6260 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6261 if (r_showtris.value > 0)
6263 if (!rsurface.texture->currentlayers->depthmask)
6264 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
6265 else if (ent == r_refdef.worldentity)
6266 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
6268 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
6269 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6272 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6274 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6275 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6276 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6277 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6282 if (r_shownormals.value > 0)
6285 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6287 VectorCopy(rsurface.vertex3f + l * 3, v);
6288 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
6289 qglVertex3f(v[0], v[1], v[2]);
6290 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6291 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6292 qglVertex3f(v[0], v[1], v[2]);
6297 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6299 VectorCopy(rsurface.vertex3f + l * 3, v);
6300 GL_Color(0, r_refdef.view.colorscale, 0, 1);
6301 qglVertex3f(v[0], v[1], v[2]);
6302 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6303 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6304 qglVertex3f(v[0], v[1], v[2]);
6309 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6311 VectorCopy(rsurface.vertex3f + l * 3, v);
6312 GL_Color(0, 0, r_refdef.view.colorscale, 1);
6313 qglVertex3f(v[0], v[1], v[2]);
6314 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6315 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6316 qglVertex3f(v[0], v[1], v[2]);
6323 rsurface.texture = NULL;
6327 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6328 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6330 int i, j, endj, f, flagsmask;
6331 msurface_t *surface;
6333 model_t *model = r_refdef.worldmodel;
6334 const int maxsurfacelist = 1024;
6335 int numsurfacelist = 0;
6336 msurface_t *surfacelist[1024];
6340 RSurf_ActiveWorldEntity();
6342 // update light styles on this submodel
6343 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6345 model_brush_lightstyleinfo_t *style;
6346 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6348 if (style->value != r_refdef.lightstylevalue[style->style])
6350 msurface_t *surfaces = model->data_surfaces;
6351 int *list = style->surfacelist;
6352 style->value = r_refdef.lightstylevalue[style->style];
6353 for (j = 0;j < style->numsurfaces;j++)
6354 surfaces[list[j]].cached_dlight = true;
6359 R_UpdateAllTextureInfo(r_refdef.worldentity);
6360 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6364 R_DrawDebugModel(r_refdef.worldentity);
6370 rsurface.uselightmaptexture = false;
6371 rsurface.texture = NULL;
6373 j = model->firstmodelsurface;
6374 endj = j + model->nummodelsurfaces;
6377 // quickly skip over non-visible surfaces
6378 for (;j < endj && !r_refdef.viewcache.world_surfacevisible[j];j++)
6380 // quickly iterate over visible surfaces
6381 for (;j < endj && r_refdef.viewcache.world_surfacevisible[j];j++)
6383 // process this surface
6384 surface = model->data_surfaces + j;
6385 // if this surface fits the criteria, add it to the list
6386 if (surface->num_triangles)
6388 // if lightmap parameters changed, rebuild lightmap texture
6389 if (surface->cached_dlight)
6390 R_BuildLightMap(r_refdef.worldentity, surface);
6391 // add face to draw list
6392 surfacelist[numsurfacelist++] = surface;
6393 r_refdef.stats.world_triangles += surface->num_triangles;
6394 if (numsurfacelist >= maxsurfacelist)
6396 r_refdef.stats.world_surfaces += numsurfacelist;
6397 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6403 r_refdef.stats.world_surfaces += numsurfacelist;
6405 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6409 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6411 int i, j, f, flagsmask;
6412 msurface_t *surface, *endsurface;
6414 model_t *model = ent->model;
6415 const int maxsurfacelist = 1024;
6416 int numsurfacelist = 0;
6417 msurface_t *surfacelist[1024];
6421 // if the model is static it doesn't matter what value we give for
6422 // wantnormals and wanttangents, so this logic uses only rules applicable
6423 // to a model, knowing that they are meaningless otherwise
6424 if (ent == r_refdef.worldentity)
6425 RSurf_ActiveWorldEntity();
6426 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6427 RSurf_ActiveModelEntity(ent, false, false);
6429 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6431 // update light styles
6432 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6434 model_brush_lightstyleinfo_t *style;
6435 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6437 if (style->value != r_refdef.lightstylevalue[style->style])
6439 msurface_t *surfaces = model->data_surfaces;
6440 int *list = style->surfacelist;
6441 style->value = r_refdef.lightstylevalue[style->style];
6442 for (j = 0;j < style->numsurfaces;j++)
6443 surfaces[list[j]].cached_dlight = true;
6448 R_UpdateAllTextureInfo(ent);
6449 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6453 R_DrawDebugModel(ent);
6459 rsurface.uselightmaptexture = false;
6460 rsurface.texture = NULL;
6462 surface = model->data_surfaces + model->firstmodelsurface;
6463 endsurface = surface + model->nummodelsurfaces;
6464 for (;surface < endsurface;surface++)
6466 // if this surface fits the criteria, add it to the list
6467 if (surface->num_triangles)
6469 // if lightmap parameters changed, rebuild lightmap texture
6470 if (surface->cached_dlight)
6471 R_BuildLightMap(ent, surface);
6472 // add face to draw list
6473 surfacelist[numsurfacelist++] = surface;
6474 r_refdef.stats.entities_triangles += surface->num_triangles;
6475 if (numsurfacelist >= maxsurfacelist)
6477 r_refdef.stats.entities_surfaces += numsurfacelist;
6478 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6483 r_refdef.stats.entities_surfaces += numsurfacelist;
6485 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);