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 r_viewcache_t r_viewcache;
38 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"};
39 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
40 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
41 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)"};
42 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
43 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
44 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"};
45 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"};
46 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
47 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"};
48 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"};
49 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"};
50 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
51 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
52 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
53 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
54 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
55 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
56 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
57 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
58 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
59 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
60 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
61 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
62 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
63 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
64 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
65 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"};
66 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"};
67 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
69 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
70 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
71 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
72 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
73 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
74 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
75 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
76 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
78 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)"};
80 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
81 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
82 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
83 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
84 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)"};
85 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)"};
87 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)"};
88 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
89 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"};
90 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
91 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
93 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
94 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
95 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
96 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
98 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
99 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
100 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
101 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
102 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
103 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
104 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
106 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
107 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
108 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
109 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)"};
111 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"};
113 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"};
115 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
117 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
118 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
119 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"};
120 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
121 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
122 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
124 extern qboolean v_flipped_state;
126 typedef struct r_glsl_bloomshader_s
129 int loc_Texture_Bloom;
131 r_glsl_bloomshader_t;
133 static struct r_bloomstate_s
138 int bloomwidth, bloomheight;
140 int screentexturewidth, screentextureheight;
141 rtexture_t *texture_screen;
143 int bloomtexturewidth, bloomtextureheight;
144 rtexture_t *texture_bloom;
146 r_glsl_bloomshader_t *shader;
148 // arrays for rendering the screen passes
149 float screentexcoord2f[8];
150 float bloomtexcoord2f[8];
151 float offsettexcoord2f[8];
155 typedef struct r_waterstate_waterplane_s
157 rtexture_t *texture_refraction;
158 rtexture_t *texture_reflection;
160 int materialflags; // combined flags of all water surfaces on this plane
161 unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
164 r_waterstate_waterplane_t;
166 #define MAX_WATERPLANES 16
168 static struct r_waterstate_s
172 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
174 int waterwidth, waterheight;
175 int texturewidth, textureheight;
177 int maxwaterplanes; // same as MAX_WATERPLANES
179 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
181 float screenscale[2];
182 float screencenter[2];
186 // shadow volume bsp struct with automatically growing nodes buffer
189 rtexture_t *r_texture_blanknormalmap;
190 rtexture_t *r_texture_white;
191 rtexture_t *r_texture_grey128;
192 rtexture_t *r_texture_black;
193 rtexture_t *r_texture_notexture;
194 rtexture_t *r_texture_whitecube;
195 rtexture_t *r_texture_normalizationcube;
196 rtexture_t *r_texture_fogattenuation;
197 //rtexture_t *r_texture_fogintensity;
199 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
200 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
202 // vertex coordinates for a quad that covers the screen exactly
203 const static float r_screenvertex3f[12] =
211 extern void R_DrawModelShadows(void);
213 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
216 for (i = 0;i < verts;i++)
227 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
230 for (i = 0;i < verts;i++)
240 // FIXME: move this to client?
243 if (gamemode == GAME_NEHAHRA)
245 Cvar_Set("gl_fogenable", "0");
246 Cvar_Set("gl_fogdensity", "0.2");
247 Cvar_Set("gl_fogred", "0.3");
248 Cvar_Set("gl_foggreen", "0.3");
249 Cvar_Set("gl_fogblue", "0.3");
251 r_refdef.fog_density = 0;
252 r_refdef.fog_red = 0;
253 r_refdef.fog_green = 0;
254 r_refdef.fog_blue = 0;
255 r_refdef.fog_alpha = 1;
256 r_refdef.fog_start = 0;
257 r_refdef.fog_end = 0;
260 float FogForDistance(vec_t dist)
262 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
263 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
266 float FogPoint_World(const vec3_t p)
268 return FogForDistance(VectorDistance((p), r_view.origin));
271 float FogPoint_Model(const vec3_t p)
273 return FogForDistance(VectorDistance((p), rsurface.modelorg));
276 static void R_BuildBlankTextures(void)
278 unsigned char data[4];
279 data[2] = 128; // normal X
280 data[1] = 128; // normal Y
281 data[0] = 255; // normal Z
282 data[3] = 128; // height
283 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
288 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
293 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
298 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
301 static void R_BuildNoTexture(void)
304 unsigned char pix[16][16][4];
305 // this makes a light grey/dark grey checkerboard texture
306 for (y = 0;y < 16;y++)
308 for (x = 0;x < 16;x++)
310 if ((y < 8) ^ (x < 8))
326 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
329 static void R_BuildWhiteCube(void)
331 unsigned char data[6*1*1*4];
332 memset(data, 255, sizeof(data));
333 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
336 static void R_BuildNormalizationCube(void)
340 vec_t s, t, intensity;
342 unsigned char data[6][NORMSIZE][NORMSIZE][4];
343 for (side = 0;side < 6;side++)
345 for (y = 0;y < NORMSIZE;y++)
347 for (x = 0;x < NORMSIZE;x++)
349 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
350 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
385 intensity = 127.0f / sqrt(DotProduct(v, v));
386 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
387 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
388 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
389 data[side][y][x][3] = 255;
393 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
396 static void R_BuildFogTexture(void)
400 unsigned char data1[FOGWIDTH][4];
401 //unsigned char data2[FOGWIDTH][4];
404 r_refdef.fogmasktable_start = r_refdef.fog_start;
405 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
406 r_refdef.fogmasktable_range = r_refdef.fogrange;
407 r_refdef.fogmasktable_density = r_refdef.fog_density;
409 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
410 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
412 d = (x * r - r_refdef.fogmasktable_start);
413 Con_Printf("%f ", d);
415 if (r_fog_exp2.integer)
416 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
418 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
419 Con_Printf(" : %f ", alpha);
420 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
421 Con_Printf(" = %f\n", alpha);
422 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
425 for (x = 0;x < FOGWIDTH;x++)
427 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
432 //data2[x][0] = 255 - b;
433 //data2[x][1] = 255 - b;
434 //data2[x][2] = 255 - b;
437 if (r_texture_fogattenuation)
439 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
440 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
444 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);
445 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
449 static const char *builtinshaderstring =
450 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
451 "// written by Forest 'LordHavoc' Hale\n"
453 "// common definitions between vertex shader and fragment shader:\n"
455 "#ifdef __GLSL_CG_DATA_TYPES\n"
456 "# define myhalf half\n"
457 "# define myhvec2 hvec2\n"
458 "# define myhvec3 hvec3\n"
459 "# define myhvec4 hvec4\n"
461 "# define myhalf float\n"
462 "# define myhvec2 vec2\n"
463 "# define myhvec3 vec3\n"
464 "# define myhvec4 vec4\n"
467 "varying vec2 TexCoord;\n"
468 "varying vec2 TexCoordLightmap;\n"
470 "//#ifdef MODE_LIGHTSOURCE\n"
471 "varying vec3 CubeVector;\n"
474 "//#ifdef MODE_LIGHTSOURCE\n"
475 "varying vec3 LightVector;\n"
477 "//# ifdef MODE_LIGHTDIRECTION\n"
478 "//varying vec3 LightVector;\n"
482 "varying vec3 EyeVector;\n"
484 "varying vec3 EyeVectorModelSpace;\n"
487 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
488 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
489 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
491 "//#ifdef MODE_WATER\n"
492 "varying vec4 ModelViewProjectionPosition;\n"
494 "//# ifdef MODE_REFRACTION\n"
495 "//varying vec4 ModelViewProjectionPosition;\n"
497 "//# ifdef USEREFLECTION\n"
498 "//varying vec4 ModelViewProjectionPosition;\n"
507 "// vertex shader specific:\n"
508 "#ifdef VERTEX_SHADER\n"
510 "uniform vec3 LightPosition;\n"
511 "uniform vec3 EyePosition;\n"
512 "uniform vec3 LightDir;\n"
514 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3)\n"
518 " gl_FrontColor = gl_Color;\n"
519 " // copy the surface texcoord\n"
520 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
521 "#ifndef MODE_LIGHTSOURCE\n"
522 "# ifndef MODE_LIGHTDIRECTION\n"
523 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
527 "#ifdef MODE_LIGHTSOURCE\n"
528 " // transform vertex position into light attenuation/cubemap space\n"
529 " // (-1 to +1 across the light box)\n"
530 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
532 " // transform unnormalized light direction into tangent space\n"
533 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
534 " // normalize it per pixel)\n"
535 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
536 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
537 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
538 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
541 "#ifdef MODE_LIGHTDIRECTION\n"
542 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
543 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
544 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
547 " // transform unnormalized eye direction into tangent space\n"
549 " vec3 EyeVectorModelSpace;\n"
551 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
552 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
553 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
554 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
556 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
557 " VectorS = gl_MultiTexCoord1.xyz;\n"
558 " VectorT = gl_MultiTexCoord2.xyz;\n"
559 " VectorR = gl_MultiTexCoord3.xyz;\n"
562 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
563 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
564 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
565 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
568 "// transform vertex to camera space, using ftransform to match non-VS\n"
570 " gl_Position = ftransform();\n"
572 "#ifdef MODE_WATER\n"
573 " ModelViewProjectionPosition = gl_Position;\n"
575 "#ifdef MODE_REFRACTION\n"
576 " ModelViewProjectionPosition = gl_Position;\n"
578 "#ifdef USEREFLECTION\n"
579 " ModelViewProjectionPosition = gl_Position;\n"
583 "#endif // VERTEX_SHADER\n"
588 "// fragment shader specific:\n"
589 "#ifdef FRAGMENT_SHADER\n"
591 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
592 "uniform sampler2D Texture_Normal;\n"
593 "uniform sampler2D Texture_Color;\n"
594 "uniform sampler2D Texture_Gloss;\n"
595 "uniform samplerCube Texture_Cube;\n"
596 "uniform sampler2D Texture_Attenuation;\n"
597 "uniform sampler2D Texture_FogMask;\n"
598 "uniform sampler2D Texture_Pants;\n"
599 "uniform sampler2D Texture_Shirt;\n"
600 "uniform sampler2D Texture_Lightmap;\n"
601 "uniform sampler2D Texture_Deluxemap;\n"
602 "uniform sampler2D Texture_Glow;\n"
603 "uniform sampler2D Texture_Reflection;\n"
604 "uniform sampler2D Texture_Refraction;\n"
606 "uniform myhvec3 LightColor;\n"
607 "uniform myhvec3 AmbientColor;\n"
608 "uniform myhvec3 DiffuseColor;\n"
609 "uniform myhvec3 SpecularColor;\n"
610 "uniform myhvec3 Color_Pants;\n"
611 "uniform myhvec3 Color_Shirt;\n"
612 "uniform myhvec3 FogColor;\n"
614 "uniform myhvec4 TintColor;\n"
617 "//#ifdef MODE_WATER\n"
618 "uniform vec4 DistortScaleRefractReflect;\n"
619 "uniform vec4 ScreenScaleRefractReflect;\n"
620 "uniform vec4 ScreenCenterRefractReflect;\n"
621 "uniform myhvec4 RefractColor;\n"
622 "uniform myhvec4 ReflectColor;\n"
623 "uniform myhalf ReflectFactor;\n"
624 "uniform myhalf ReflectOffset;\n"
626 "//# ifdef MODE_REFRACTION\n"
627 "//uniform vec4 DistortScaleRefractReflect;\n"
628 "//uniform vec4 ScreenScaleRefractReflect;\n"
629 "//uniform vec4 ScreenCenterRefractReflect;\n"
630 "//uniform myhvec4 RefractColor;\n"
631 "//# ifdef USEREFLECTION\n"
632 "//uniform myhvec4 ReflectColor;\n"
635 "//# ifdef USEREFLECTION\n"
636 "//uniform vec4 DistortScaleRefractReflect;\n"
637 "//uniform vec4 ScreenScaleRefractReflect;\n"
638 "//uniform vec4 ScreenCenterRefractReflect;\n"
639 "//uniform myhvec4 ReflectColor;\n"
644 "uniform myhalf GlowScale;\n"
645 "uniform myhalf SceneBrightness;\n"
646 "#ifdef USECONTRASTBOOST\n"
647 "uniform myhalf ContrastBoostCoeff;\n"
650 "uniform float OffsetMapping_Scale;\n"
651 "uniform float OffsetMapping_Bias;\n"
652 "uniform float FogRangeRecip;\n"
654 "uniform myhalf AmbientScale;\n"
655 "uniform myhalf DiffuseScale;\n"
656 "uniform myhalf SpecularScale;\n"
657 "uniform myhalf SpecularPower;\n"
659 "#ifdef USEOFFSETMAPPING\n"
660 "vec2 OffsetMapping(vec2 TexCoord)\n"
662 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
663 " // 14 sample relief mapping: linear search and then binary search\n"
664 " // this basically steps forward a small amount repeatedly until it finds\n"
665 " // itself inside solid, then jitters forward and back using decreasing\n"
666 " // amounts to find the impact\n"
667 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
668 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
669 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
670 " vec3 RT = vec3(TexCoord, 1);\n"
671 " OffsetVector *= 0.1;\n"
672 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
682 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
683 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
684 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
685 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
688 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
689 " // this basically moves forward the full distance, and then backs up based\n"
690 " // on height of samples\n"
691 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
692 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
693 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
694 " TexCoord += OffsetVector;\n"
695 " OffsetVector *= 0.333;\n"
696 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
697 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
698 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
699 " return TexCoord;\n"
702 "#endif // USEOFFSETMAPPING\n"
704 "#ifdef MODE_WATER\n"
709 "#ifdef USEOFFSETMAPPING\n"
710 " // apply offsetmapping\n"
711 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
712 "#define TexCoord TexCoordOffset\n"
715 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
716 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
717 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
718 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 5.0) * ReflectFactor + ReflectOffset;\n"
719 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
722 "#else // MODE_WATER\n"
723 "#ifdef MODE_REFRACTION\n"
725 "// refraction pass\n"
728 "#ifdef USEOFFSETMAPPING\n"
729 " // apply offsetmapping\n"
730 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
731 "#define TexCoord TexCoordOffset\n"
734 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
735 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
736 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
737 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
740 "#else // MODE_REFRACTION\n"
743 "#ifdef USEOFFSETMAPPING\n"
744 " // apply offsetmapping\n"
745 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
746 "#define TexCoord TexCoordOffset\n"
749 " // combine the diffuse textures (base, pants, shirt)\n"
750 " myhvec4 color = myhvec4(texture2D(Texture_Color, TexCoord));\n"
751 "#ifdef USECOLORMAPPING\n"
752 " color.rgb += myhvec3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhvec3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
758 "#ifdef MODE_LIGHTSOURCE\n"
761 " // calculate surface normal, light normal, and specular normal\n"
762 " // compute color intensity for the two textures (colormap and glossmap)\n"
763 " // scale by light color and attenuation as efficiently as possible\n"
764 " // (do as much scalar math as possible rather than vector math)\n"
765 "# ifdef USESPECULAR\n"
766 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
767 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
768 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
770 " // calculate directional shading\n"
771 " 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"
773 "# ifdef USEDIFFUSE\n"
774 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
775 " myhvec3 diffusenormal = myhvec3(normalize(LightVector));\n"
777 " // calculate directional shading\n"
778 " 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"
780 " // calculate directionless shading\n"
781 " color.rgb = color.rgb * LightColor * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
785 "# ifdef USECUBEFILTER\n"
786 " // apply light cubemap filter\n"
787 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
788 " color.rgb *= myhvec3(textureCube(Texture_Cube, CubeVector));\n"
790 "#endif // MODE_LIGHTSOURCE\n"
795 "#ifdef MODE_LIGHTDIRECTION\n"
796 " // directional model lighting\n"
797 "# ifdef USESPECULAR\n"
798 " // get the surface normal and light normal\n"
799 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
800 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
802 " // calculate directional shading\n"
803 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
804 " myhvec3 specularnormal = normalize(diffusenormal + myhvec3(normalize(EyeVector)));\n"
805 " color.rgb += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
807 "# ifdef USEDIFFUSE\n"
808 " // get the surface normal and light normal\n"
809 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
810 " myhvec3 diffusenormal = myhvec3(LightVector);\n"
812 " // calculate directional shading\n"
813 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
815 " color.rgb *= AmbientColor;\n"
819 " color.a *= TintColor.a;\n"
820 "#endif // MODE_LIGHTDIRECTION\n"
825 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
826 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
828 " // get the surface normal and light normal\n"
829 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
831 " myhvec3 diffusenormal_modelspace = myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5);\n"
832 " myhvec3 diffusenormal = normalize(myhvec3(dot(diffusenormal_modelspace, myhvec3(VectorS)), dot(diffusenormal_modelspace, myhvec3(VectorT)), dot(diffusenormal_modelspace, myhvec3(VectorR))));\n"
833 " // calculate directional shading\n"
834 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
835 "# ifdef USESPECULAR\n"
836 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
837 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
840 " // apply lightmap color\n"
841 " color.rgb = color.rgb * AmbientScale + tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
843 " color *= TintColor;\n"
844 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
849 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
850 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
852 " // get the surface normal and light normal\n"
853 " myhvec3 surfacenormal = normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5));\n"
855 " myhvec3 diffusenormal = normalize(myhvec3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhvec3(0.5));\n"
856 " // calculate directional shading\n"
857 " myhvec3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
858 "# ifdef USESPECULAR\n"
859 " myhvec3 specularnormal = myhvec3(normalize(diffusenormal + myhvec3(normalize(EyeVector))));\n"
860 " tempcolor += myhvec3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
863 " // apply lightmap color\n"
864 " color.rgb = color.rgb * AmbientScale + tempcolor * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
866 " color *= TintColor;\n"
867 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
872 "#ifdef MODE_LIGHTMAP\n"
873 " // apply lightmap color\n"
874 " color.rgb = color.rgb * myhvec3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
876 " color *= TintColor;\n"
877 "#endif // MODE_LIGHTMAP\n"
882 "#ifdef MODE_VERTEXCOLOR\n"
883 " // apply lightmap color\n"
884 " color.rgb = color.rgb * myhvec3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
886 " color *= TintColor;\n"
887 "#endif // MODE_VERTEXCOLOR\n"
892 "#ifdef MODE_FLATCOLOR\n"
893 " color *= TintColor;\n"
894 "#endif // MODE_FLATCOLOR\n"
904 " color.rgb += myhvec3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
907 "#ifdef USECONTRASTBOOST\n"
908 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhvec3(1, 1, 1));\n"
911 " color.rgb *= SceneBrightness;\n"
913 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
915 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
918 " // 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"
919 "#ifdef USEREFLECTION\n"
920 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
921 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
922 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhvec3(texture2D(Texture_Normal, TexCoord)) - myhvec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
923 " color.rgb = mix(color.rgb, myhvec3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
926 " gl_FragColor = vec4(color);\n"
928 "#endif // MODE_REFRACTION\n"
929 "#endif // MODE_WATER\n"
931 "#endif // FRAGMENT_SHADER\n"
934 #define SHADERPERMUTATION_COLORMAPPING (1<<0) // indicates this is a colormapped skin
935 #define SHADERPERMUTATION_CONTRASTBOOST (1<<1) // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
936 #define SHADERPERMUTATION_FOG (1<<2) // tint the color by fog color or black if using additive blend mode
937 #define SHADERPERMUTATION_CUBEFILTER (1<<3) // (lightsource) use cubemap light filter
938 #define SHADERPERMUTATION_GLOW (1<<4) // (lightmap) blend in an additive glow texture
939 #define SHADERPERMUTATION_DIFFUSE (1<<5) // (lightsource) whether to use directional shading
940 #define SHADERPERMUTATION_SPECULAR (1<<6) // (lightsource or deluxemapping) render specular effects
941 #define SHADERPERMUTATION_REFLECTION (1<<7) // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
942 #define SHADERPERMUTATION_OFFSETMAPPING (1<<8) // adjust texcoords to roughly simulate a displacement mapped surface
943 #define SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING (1<<9) // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
944 #define SHADERPERMUTATION_MODEBASE (1<<10) // multiplier for the SHADERMODE_ values to get a valid index
946 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
947 const char *shaderpermutationinfo[][2] =
949 {"#define USECOLORMAPPING\n", " colormapping"},
950 {"#define USECONTRASTBOOST\n", " contrastboost"},
951 {"#define USEFOG\n", " fog"},
952 {"#define USECUBEFILTER\n", " cubefilter"},
953 {"#define USEGLOW\n", " glow"},
954 {"#define USEDIFFUSE\n", " diffuse"},
955 {"#define USESPECULAR\n", " specular"},
956 {"#define USEREFLECTION\n", " reflection"},
957 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
958 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
962 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
963 typedef enum shadermode_e
965 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
966 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
967 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
968 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
969 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
970 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
971 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
972 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
973 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
978 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
979 const char *shadermodeinfo[][2] =
981 {"#define MODE_FLATCOLOR\n", " flatcolor"},
982 {"#define MODE_VERTEXCOLOR\n", " vertexcolor"},
983 {"#define MODE_LIGHTMAP\n", " lightmap"},
984 {"#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
985 {"#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
986 {"#define MODE_LIGHTDIRECTION\n", " lightdirection"},
987 {"#define MODE_LIGHTSOURCE\n", " lightsource"},
988 {"#define MODE_REFRACTION\n", " refraction"},
989 {"#define MODE_WATER\n", " water"},
993 #define SHADERPERMUTATION_INDICES (SHADERPERMUTATION_MODEBASE * SHADERMODE_COUNT)
995 typedef struct r_glsl_permutation_s
997 // indicates if we have tried compiling this permutation already
999 // 0 if compilation failed
1001 // locations of detected uniforms in program object, or -1 if not found
1002 int loc_Texture_Normal;
1003 int loc_Texture_Color;
1004 int loc_Texture_Gloss;
1005 int loc_Texture_Cube;
1006 int loc_Texture_Attenuation;
1007 int loc_Texture_FogMask;
1008 int loc_Texture_Pants;
1009 int loc_Texture_Shirt;
1010 int loc_Texture_Lightmap;
1011 int loc_Texture_Deluxemap;
1012 int loc_Texture_Glow;
1013 int loc_Texture_Refraction;
1014 int loc_Texture_Reflection;
1016 int loc_LightPosition;
1017 int loc_EyePosition;
1019 int loc_Color_Pants;
1020 int loc_Color_Shirt;
1021 int loc_FogRangeRecip;
1022 int loc_AmbientScale;
1023 int loc_DiffuseScale;
1024 int loc_SpecularScale;
1025 int loc_SpecularPower;
1027 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1028 int loc_OffsetMapping_Scale;
1030 int loc_AmbientColor;
1031 int loc_DiffuseColor;
1032 int loc_SpecularColor;
1034 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1035 int loc_DistortScaleRefractReflect;
1036 int loc_ScreenScaleRefractReflect;
1037 int loc_ScreenCenterRefractReflect;
1038 int loc_RefractColor;
1039 int loc_ReflectColor;
1040 int loc_ReflectFactor;
1041 int loc_ReflectOffset;
1043 r_glsl_permutation_t;
1045 // information about each possible shader permutation
1046 r_glsl_permutation_t r_glsl_permutations[SHADERPERMUTATION_INDICES];
1047 // currently selected permutation
1048 r_glsl_permutation_t *r_glsl_permutation;
1050 // these are additional flags used only by R_GLSL_CompilePermutation
1051 #define SHADERTYPE_USES_VERTEXSHADER (1<<0)
1052 #define SHADERTYPE_USES_GEOMETRYSHADER (1<<1)
1053 #define SHADERTYPE_USES_FRAGMENTSHADER (1<<2)
1055 static void R_GLSL_CompilePermutation(const char *filename, int permutation, int shadertype)
1058 qboolean shaderfound;
1059 r_glsl_permutation_t *p = r_glsl_permutations + permutation;
1060 int vertstrings_count;
1061 int geomstrings_count;
1062 int fragstrings_count;
1064 const char *vertstrings_list[32+1];
1065 const char *geomstrings_list[32+1];
1066 const char *fragstrings_list[32+1];
1067 char permutationname[256];
1072 vertstrings_list[0] = "#define VERTEX_SHADER\n";
1073 geomstrings_list[0] = "#define GEOMETRY_SHADER\n";
1074 fragstrings_list[0] = "#define FRAGMENT_SHADER\n";
1075 vertstrings_count = 1;
1076 geomstrings_count = 1;
1077 fragstrings_count = 1;
1078 permutationname[0] = 0;
1079 i = permutation / SHADERPERMUTATION_MODEBASE;
1080 vertstrings_list[vertstrings_count++] = shadermodeinfo[i][0];
1081 geomstrings_list[geomstrings_count++] = shadermodeinfo[i][0];
1082 fragstrings_list[fragstrings_count++] = shadermodeinfo[i][0];
1083 strlcat(permutationname, shadermodeinfo[i][1], sizeof(permutationname));
1084 for (i = 0;shaderpermutationinfo[i][0];i++)
1086 if (permutation & (1<<i))
1088 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i][0];
1089 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i][0];
1090 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i][0];
1091 strlcat(permutationname, shaderpermutationinfo[i][1], sizeof(permutationname));
1095 // keep line numbers correct
1096 vertstrings_list[vertstrings_count++] = "\n";
1097 geomstrings_list[geomstrings_count++] = "\n";
1098 fragstrings_list[fragstrings_count++] = "\n";
1101 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1102 shaderfound = false;
1105 Con_DPrint("from disk... ");
1106 vertstrings_list[vertstrings_count++] = shaderstring;
1107 geomstrings_list[geomstrings_count++] = shaderstring;
1108 fragstrings_list[fragstrings_count++] = shaderstring;
1111 else if (!strcmp(filename, "glsl/default.glsl"))
1113 vertstrings_list[vertstrings_count++] = builtinshaderstring;
1114 geomstrings_list[geomstrings_count++] = builtinshaderstring;
1115 fragstrings_list[fragstrings_count++] = builtinshaderstring;
1118 // clear any lists that are not needed by this shader
1119 if (!(shadertype & SHADERTYPE_USES_VERTEXSHADER))
1120 vertstrings_count = 0;
1121 if (!(shadertype & SHADERTYPE_USES_GEOMETRYSHADER))
1122 geomstrings_count = 0;
1123 if (!(shadertype & SHADERTYPE_USES_FRAGMENTSHADER))
1124 fragstrings_count = 0;
1125 // compile the shader program
1126 if (shaderfound && vertstrings_count + geomstrings_count + fragstrings_count)
1127 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1131 qglUseProgramObjectARB(p->program);CHECKGLERROR
1132 // look up all the uniform variable names we care about, so we don't
1133 // have to look them up every time we set them
1134 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1135 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1136 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1137 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1138 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1139 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1140 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1141 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1142 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1143 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1144 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1145 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1146 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1147 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1148 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1149 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1150 p->loc_LightColor = qglGetUniformLocationARB(p->program, "LightColor");
1151 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1152 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1153 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1154 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1155 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1156 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1157 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1158 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1159 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1160 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1161 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1162 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1163 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1164 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1165 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1166 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1167 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1168 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1169 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1170 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1171 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1172 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1173 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1174 // initialize the samplers to refer to the texture units we use
1175 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal, 0);
1176 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color, 1);
1177 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss, 2);
1178 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube, 3);
1179 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask, 4);
1180 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants, 5);
1181 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt, 6);
1182 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap, 7);
1183 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap, 8);
1184 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow, 9);
1185 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation, 10);
1186 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction, 11);
1187 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection, 12);
1189 qglUseProgramObjectARB(0);CHECKGLERROR
1190 if (developer.integer)
1191 Con_Printf("GLSL shader %s :%s compiled.\n", filename, permutationname);
1195 if (developer.integer)
1196 Con_Printf("GLSL shader %s :%s failed! source code line offset for above errors is %i.\n", permutationname, filename, -(vertstrings_count - 1));
1198 Con_Printf("GLSL shader %s :%s failed! some features may not work properly.\n", permutationname, filename);
1201 Mem_Free(shaderstring);
1204 void R_GLSL_Restart_f(void)
1207 for (i = 0;i < SHADERPERMUTATION_INDICES;i++)
1208 if (r_glsl_permutations[i].program)
1209 GL_Backend_FreeProgram(r_glsl_permutations[i].program);
1210 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1213 void R_GLSL_DumpShader_f(void)
1217 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1220 Con_Printf("failed to write to glsl/default.glsl\n");
1224 FS_Print(file, "// The engine may define the following macros:\n");
1225 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1226 for (i = 0;shadermodeinfo[i][0];i++)
1227 FS_Printf(file, "// %s", shadermodeinfo[i][0]);
1228 for (i = 0;shaderpermutationinfo[i][0];i++)
1229 FS_Printf(file, "// %s", shaderpermutationinfo[i][0]);
1230 FS_Print(file, "\n");
1231 FS_Print(file, builtinshaderstring);
1234 Con_Printf("glsl/default.glsl written\n");
1237 extern rtexture_t *r_shadow_attenuationgradienttexture;
1238 extern rtexture_t *r_shadow_attenuation2dtexture;
1239 extern rtexture_t *r_shadow_attenuation3dtexture;
1240 int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1242 // select a permutation of the lighting shader appropriate to this
1243 // combination of texture, entity, light source, and fogging, only use the
1244 // minimum features necessary to avoid wasting rendering time in the
1245 // fragment shader on features that are not being used
1246 const char *shaderfilename = NULL;
1247 unsigned int permutation = 0;
1248 unsigned int shadertype = 0;
1249 shadermode_t mode = 0;
1250 r_glsl_permutation = NULL;
1251 shaderfilename = "glsl/default.glsl";
1252 shadertype = SHADERTYPE_USES_VERTEXSHADER | SHADERTYPE_USES_FRAGMENTSHADER;
1253 // TODO: implement geometry-shader based shadow volumes someday
1254 if (r_glsl_offsetmapping.integer)
1256 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1257 if (r_glsl_offsetmapping_reliefmapping.integer)
1258 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1260 if (rsurfacepass == RSURFPASS_BACKGROUND)
1262 // distorted background
1263 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1264 mode = SHADERMODE_WATER;
1266 mode = SHADERMODE_REFRACTION;
1268 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1271 mode = SHADERMODE_LIGHTSOURCE;
1272 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1273 permutation |= SHADERPERMUTATION_CUBEFILTER;
1274 if (diffusescale > 0)
1275 permutation |= SHADERPERMUTATION_DIFFUSE;
1276 if (specularscale > 0)
1277 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1278 if (r_refdef.fogenabled)
1279 permutation |= SHADERPERMUTATION_FOG;
1280 if (rsurface.texture->colormapping)
1281 permutation |= SHADERPERMUTATION_COLORMAPPING;
1282 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1283 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1285 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1287 // unshaded geometry (fullbright or ambient model lighting)
1288 mode = SHADERMODE_FLATCOLOR;
1289 if (rsurface.texture->currentskinframe->glow)
1290 permutation |= SHADERPERMUTATION_GLOW;
1291 if (r_refdef.fogenabled)
1292 permutation |= SHADERPERMUTATION_FOG;
1293 if (rsurface.texture->colormapping)
1294 permutation |= SHADERPERMUTATION_COLORMAPPING;
1295 if (r_glsl_offsetmapping.integer)
1297 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1298 if (r_glsl_offsetmapping_reliefmapping.integer)
1299 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1301 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1302 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1303 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1304 permutation |= SHADERPERMUTATION_REFLECTION;
1306 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1308 // directional model lighting
1309 mode = SHADERMODE_LIGHTDIRECTION;
1310 if (rsurface.texture->currentskinframe->glow)
1311 permutation |= SHADERPERMUTATION_GLOW;
1312 permutation |= SHADERPERMUTATION_DIFFUSE;
1313 if (specularscale > 0)
1314 permutation |= SHADERPERMUTATION_SPECULAR;
1315 if (r_refdef.fogenabled)
1316 permutation |= SHADERPERMUTATION_FOG;
1317 if (rsurface.texture->colormapping)
1318 permutation |= SHADERPERMUTATION_COLORMAPPING;
1319 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1320 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1321 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1322 permutation |= SHADERPERMUTATION_REFLECTION;
1324 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1326 // ambient model lighting
1327 mode = SHADERMODE_LIGHTDIRECTION;
1328 if (rsurface.texture->currentskinframe->glow)
1329 permutation |= SHADERPERMUTATION_GLOW;
1330 if (r_refdef.fogenabled)
1331 permutation |= SHADERPERMUTATION_FOG;
1332 if (rsurface.texture->colormapping)
1333 permutation |= SHADERPERMUTATION_COLORMAPPING;
1334 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1335 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1336 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1337 permutation |= SHADERPERMUTATION_REFLECTION;
1342 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
1344 // deluxemapping (light direction texture)
1345 if (rsurface.uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
1346 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1348 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1349 if (specularscale > 0)
1350 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1352 else if (r_glsl_deluxemapping.integer >= 2)
1354 // fake deluxemapping (uniform light direction in tangentspace)
1355 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1356 if (specularscale > 0)
1357 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1359 else if (rsurface.uselightmaptexture)
1361 // ordinary lightmapping (q1bsp, q3bsp)
1362 mode = SHADERMODE_LIGHTMAP;
1366 // ordinary vertex coloring (q3bsp)
1367 mode = SHADERMODE_VERTEXCOLOR;
1369 if (rsurface.texture->currentskinframe->glow)
1370 permutation |= SHADERPERMUTATION_GLOW;
1371 if (r_refdef.fogenabled)
1372 permutation |= SHADERPERMUTATION_FOG;
1373 if (rsurface.texture->colormapping)
1374 permutation |= SHADERPERMUTATION_COLORMAPPING;
1375 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1376 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1377 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1378 permutation |= SHADERPERMUTATION_REFLECTION;
1380 permutation |= mode * SHADERPERMUTATION_MODEBASE;
1381 if (!r_glsl_permutations[permutation].program)
1383 if (!r_glsl_permutations[permutation].compiled)
1384 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1385 if (!r_glsl_permutations[permutation].program)
1387 // remove features until we find a valid permutation
1389 for (i = (SHADERPERMUTATION_MODEBASE >> 1);;i>>=1)
1393 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");
1394 Cvar_SetValueQuick(&r_glsl, 0);
1395 return 0; // no bit left to clear
1397 // reduce i more quickly whenever it would not remove any bits
1398 if (!(permutation & i))
1401 if (!r_glsl_permutations[permutation].compiled)
1402 R_GLSL_CompilePermutation(shaderfilename, permutation, shadertype);
1403 if (r_glsl_permutations[permutation].program)
1408 r_glsl_permutation = r_glsl_permutations + permutation;
1410 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1411 if (mode == SHADERMODE_LIGHTSOURCE)
1413 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1414 if (permutation & SHADERPERMUTATION_DIFFUSE)
1416 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
1417 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1418 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1419 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1423 // ambient only is simpler
1424 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale);
1425 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1426 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1427 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1430 else if (mode == SHADERMODE_LIGHTDIRECTION)
1432 if (r_glsl_permutation->loc_AmbientColor >= 0)
1433 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);
1434 if (r_glsl_permutation->loc_DiffuseColor >= 0)
1435 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);
1436 if (r_glsl_permutation->loc_SpecularColor >= 0)
1437 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);
1438 if (r_glsl_permutation->loc_LightDir >= 0)
1439 qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1443 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
1444 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1445 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1447 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]);
1448 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1449 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1451 // The formula used is actually:
1452 // color.rgb *= SceneBrightness;
1453 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1454 // I simplify that to
1455 // color.rgb *= [[SceneBrightness * ContrastBoost]];
1456 // color.rgb /= [[(ContrastBoost - 1) / ContrastBoost]] * color.rgb + 1;
1458 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[(ContrastBoost - 1) * SceneBrightness]] * color.rgb + 1);
1459 // and do [[calculations]] here in the engine
1460 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, (r_glsl_contrastboost.value - 1) * r_view.colorscale);
1461 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale * r_glsl_contrastboost.value);
1464 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_view.colorscale);
1465 if (r_glsl_permutation->loc_FogColor >= 0)
1467 // additive passes are only darkened by fog, not tinted
1468 if (rsurface.rtlight || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD))
1469 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1471 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1473 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1474 if (r_glsl_permutation->loc_Color_Pants >= 0)
1476 if (rsurface.texture->currentskinframe->pants)
1477 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1479 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1481 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1483 if (rsurface.texture->currentskinframe->shirt)
1484 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1486 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1488 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1489 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1490 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1491 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);
1492 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]);
1493 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]);
1494 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1495 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1496 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1497 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1502 #define SKINFRAME_HASH 1024
1506 int loadsequence; // incremented each level change
1507 memexpandablearray_t array;
1508 skinframe_t *hash[SKINFRAME_HASH];
1512 void R_SkinFrame_PrepareForPurge(void)
1514 r_skinframe.loadsequence++;
1515 // wrap it without hitting zero
1516 if (r_skinframe.loadsequence >= 200)
1517 r_skinframe.loadsequence = 1;
1520 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1524 // mark the skinframe as used for the purging code
1525 skinframe->loadsequence = r_skinframe.loadsequence;
1528 void R_SkinFrame_Purge(void)
1532 for (i = 0;i < SKINFRAME_HASH;i++)
1534 for (s = r_skinframe.hash[i];s;s = s->next)
1536 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1538 if (s->merged == s->base)
1540 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1541 R_PurgeTexture(s->stain );s->stain = NULL;
1542 R_PurgeTexture(s->merged);s->merged = NULL;
1543 R_PurgeTexture(s->base );s->base = NULL;
1544 R_PurgeTexture(s->pants );s->pants = NULL;
1545 R_PurgeTexture(s->shirt );s->shirt = NULL;
1546 R_PurgeTexture(s->nmap );s->nmap = NULL;
1547 R_PurgeTexture(s->gloss );s->gloss = NULL;
1548 R_PurgeTexture(s->glow );s->glow = NULL;
1549 R_PurgeTexture(s->fog );s->fog = NULL;
1550 s->loadsequence = 0;
1556 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1558 char basename[MAX_QPATH];
1560 Image_StripImageExtension(name, basename, sizeof(basename));
1562 if( last == NULL ) {
1564 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1565 item = r_skinframe.hash[hashindex];
1570 // linearly search through the hash bucket
1571 for( ; item ; item = item->next ) {
1572 if( !strcmp( item->basename, basename ) ) {
1579 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1583 char basename[MAX_QPATH];
1585 Image_StripImageExtension(name, basename, sizeof(basename));
1587 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1588 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1589 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1593 rtexture_t *dyntexture;
1594 // check whether its a dynamic texture
1595 dyntexture = CL_GetDynTexture( basename );
1596 if (!add && !dyntexture)
1598 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1599 memset(item, 0, sizeof(*item));
1600 strlcpy(item->basename, basename, sizeof(item->basename));
1601 item->base = dyntexture; // either NULL or dyntexture handle
1602 item->textureflags = textureflags;
1603 item->comparewidth = comparewidth;
1604 item->compareheight = compareheight;
1605 item->comparecrc = comparecrc;
1606 item->next = r_skinframe.hash[hashindex];
1607 r_skinframe.hash[hashindex] = item;
1609 else if( item->base == NULL )
1611 rtexture_t *dyntexture;
1612 // check whether its a dynamic texture
1613 // 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]
1614 dyntexture = CL_GetDynTexture( basename );
1615 item->base = dyntexture; // either NULL or dyntexture handle
1618 R_SkinFrame_MarkUsed(item);
1622 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1624 // FIXME: it should be possible to disable loading various layers using
1625 // cvars, to prevent wasted loading time and memory usage if the user does
1627 qboolean loadnormalmap = true;
1628 qboolean loadgloss = true;
1629 qboolean loadpantsandshirt = true;
1630 qboolean loadglow = true;
1632 unsigned char *pixels;
1633 unsigned char *bumppixels;
1634 unsigned char *basepixels = NULL;
1635 int basepixels_width;
1636 int basepixels_height;
1637 skinframe_t *skinframe;
1639 if (cls.state == ca_dedicated)
1642 // return an existing skinframe if already loaded
1643 // if loading of the first image fails, don't make a new skinframe as it
1644 // would cause all future lookups of this to be missing
1645 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1646 if (skinframe && skinframe->base)
1649 basepixels = loadimagepixelsbgra(name, complain, true);
1650 if (basepixels == NULL)
1653 // we've got some pixels to store, so really allocate this new texture now
1655 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1656 skinframe->stain = NULL;
1657 skinframe->merged = NULL;
1658 skinframe->base = r_texture_notexture;
1659 skinframe->pants = NULL;
1660 skinframe->shirt = NULL;
1661 skinframe->nmap = r_texture_blanknormalmap;
1662 skinframe->gloss = NULL;
1663 skinframe->glow = NULL;
1664 skinframe->fog = NULL;
1666 basepixels_width = image_width;
1667 basepixels_height = image_height;
1668 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);
1670 if (textureflags & TEXF_ALPHA)
1672 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1673 if (basepixels[j] < 255)
1675 if (j < basepixels_width * basepixels_height * 4)
1677 // has transparent pixels
1678 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1679 for (j = 0;j < image_width * image_height * 4;j += 4)
1684 pixels[j+3] = basepixels[j+3];
1686 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);
1691 // _norm is the name used by tenebrae and has been adopted as standard
1694 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1696 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);
1700 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1702 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1703 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1704 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);
1706 Mem_Free(bumppixels);
1708 else if (r_shadow_bumpscale_basetexture.value > 0)
1710 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1711 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1712 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);
1716 // _luma is supported for tenebrae compatibility
1717 // (I think it's a very stupid name, but oh well)
1718 // _glow is the preferred name
1719 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;}
1720 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;}
1721 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;}
1722 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;}
1725 Mem_Free(basepixels);
1730 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)
1735 for (i = 0;i < width*height;i++)
1736 if (((unsigned char *)&palette[in[i]])[3] > 0)
1738 if (i == width*height)
1741 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1744 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
1745 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
1748 unsigned char *temp1, *temp2;
1749 skinframe_t *skinframe;
1751 if (cls.state == ca_dedicated)
1754 // if already loaded just return it, otherwise make a new skinframe
1755 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
1756 if (skinframe && skinframe->base)
1759 skinframe->stain = NULL;
1760 skinframe->merged = NULL;
1761 skinframe->base = r_texture_notexture;
1762 skinframe->pants = NULL;
1763 skinframe->shirt = NULL;
1764 skinframe->nmap = r_texture_blanknormalmap;
1765 skinframe->gloss = NULL;
1766 skinframe->glow = NULL;
1767 skinframe->fog = NULL;
1769 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1773 if (r_shadow_bumpscale_basetexture.value > 0)
1775 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1776 temp2 = temp1 + width * height * 4;
1777 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1778 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1781 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1782 if (textureflags & TEXF_ALPHA)
1784 for (i = 3;i < width * height * 4;i += 4)
1785 if (skindata[i] < 255)
1787 if (i < width * height * 4)
1789 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1790 memcpy(fogpixels, skindata, width * height * 4);
1791 for (i = 0;i < width * height * 4;i += 4)
1792 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1793 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1794 Mem_Free(fogpixels);
1801 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
1804 unsigned char *temp1, *temp2;
1805 skinframe_t *skinframe;
1807 if (cls.state == ca_dedicated)
1810 // if already loaded just return it, otherwise make a new skinframe
1811 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
1812 if (skinframe && skinframe->base)
1815 skinframe->stain = NULL;
1816 skinframe->merged = NULL;
1817 skinframe->base = r_texture_notexture;
1818 skinframe->pants = NULL;
1819 skinframe->shirt = NULL;
1820 skinframe->nmap = r_texture_blanknormalmap;
1821 skinframe->gloss = NULL;
1822 skinframe->glow = NULL;
1823 skinframe->fog = NULL;
1825 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1829 if (r_shadow_bumpscale_basetexture.value > 0)
1831 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1832 temp2 = temp1 + width * height * 4;
1833 // use either a custom palette or the quake palette
1834 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
1835 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1836 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1839 // use either a custom palette, or the quake palette
1840 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
1841 if (loadglowtexture)
1842 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
1843 if (loadpantsandshirt)
1845 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
1846 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
1848 if (skinframe->pants || skinframe->shirt)
1849 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
1850 if (textureflags & TEXF_ALPHA)
1852 for (i = 0;i < width * height;i++)
1853 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
1855 if (i < width * height)
1856 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
1862 skinframe_t *R_SkinFrame_LoadMissing(void)
1864 skinframe_t *skinframe;
1866 if (cls.state == ca_dedicated)
1869 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
1870 skinframe->stain = NULL;
1871 skinframe->merged = NULL;
1872 skinframe->base = r_texture_notexture;
1873 skinframe->pants = NULL;
1874 skinframe->shirt = NULL;
1875 skinframe->nmap = r_texture_blanknormalmap;
1876 skinframe->gloss = NULL;
1877 skinframe->glow = NULL;
1878 skinframe->fog = NULL;
1883 void gl_main_start(void)
1885 memset(r_qwskincache, 0, sizeof(r_qwskincache));
1886 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
1888 // set up r_skinframe loading system for textures
1889 memset(&r_skinframe, 0, sizeof(r_skinframe));
1890 r_skinframe.loadsequence = 1;
1891 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
1893 r_main_texturepool = R_AllocTexturePool();
1894 R_BuildBlankTextures();
1896 if (gl_texturecubemap)
1899 R_BuildNormalizationCube();
1901 r_texture_fogattenuation = NULL;
1902 //r_texture_fogintensity = NULL;
1903 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
1904 memset(&r_waterstate, 0, sizeof(r_waterstate));
1905 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1906 memset(&r_svbsp, 0, sizeof (r_svbsp));
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_view.numfrustumplanes;i++)
2104 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2107 p = r_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_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_viewcache.world_leafvisible, ent->mins, ent->maxs));
2215 if(r_cullentities_trace.integer)
2217 for (i = 0;i < r_refdef.numentities;i++)
2219 ent = r_refdef.entities[i];
2220 if(r_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_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_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_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_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_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_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_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_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_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
2347 VectorNegate(r_view.left, r_view.right);
2350 r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
2351 r_view.frustum[0].normal[1] = 0 - 0;
2352 r_view.frustum[0].normal[2] = -1 - 0;
2353 r_view.frustum[1].normal[0] = 0 + 1.0 / r_view.frustum_x;
2354 r_view.frustum[1].normal[1] = 0 + 0;
2355 r_view.frustum[1].normal[2] = -1 + 0;
2356 r_view.frustum[2].normal[0] = 0 - 0;
2357 r_view.frustum[2].normal[1] = 0 - 1.0 / r_view.frustum_y;
2358 r_view.frustum[2].normal[2] = -1 - 0;
2359 r_view.frustum[3].normal[0] = 0 + 0;
2360 r_view.frustum[3].normal[1] = 0 + 1.0 / r_view.frustum_y;
2361 r_view.frustum[3].normal[2] = -1 + 0;
2365 zNear = r_refdef.nearclip;
2366 nudge = 1.0 - 1.0 / (1<<23);
2367 r_view.frustum[4].normal[0] = 0 - 0;
2368 r_view.frustum[4].normal[1] = 0 - 0;
2369 r_view.frustum[4].normal[2] = -1 - -nudge;
2370 r_view.frustum[4].dist = 0 - -2 * zNear * nudge;
2371 r_view.frustum[5].normal[0] = 0 + 0;
2372 r_view.frustum[5].normal[1] = 0 + 0;
2373 r_view.frustum[5].normal[2] = -1 + -nudge;
2374 r_view.frustum[5].dist = 0 + -2 * zNear * nudge;
2380 r_view.frustum[0].normal[0] = m[3] - m[0];
2381 r_view.frustum[0].normal[1] = m[7] - m[4];
2382 r_view.frustum[0].normal[2] = m[11] - m[8];
2383 r_view.frustum[0].dist = m[15] - m[12];
2385 r_view.frustum[1].normal[0] = m[3] + m[0];
2386 r_view.frustum[1].normal[1] = m[7] + m[4];
2387 r_view.frustum[1].normal[2] = m[11] + m[8];
2388 r_view.frustum[1].dist = m[15] + m[12];
2390 r_view.frustum[2].normal[0] = m[3] - m[1];
2391 r_view.frustum[2].normal[1] = m[7] - m[5];
2392 r_view.frustum[2].normal[2] = m[11] - m[9];
2393 r_view.frustum[2].dist = m[15] - m[13];
2395 r_view.frustum[3].normal[0] = m[3] + m[1];
2396 r_view.frustum[3].normal[1] = m[7] + m[5];
2397 r_view.frustum[3].normal[2] = m[11] + m[9];
2398 r_view.frustum[3].dist = m[15] + m[13];
2400 r_view.frustum[4].normal[0] = m[3] - m[2];
2401 r_view.frustum[4].normal[1] = m[7] - m[6];
2402 r_view.frustum[4].normal[2] = m[11] - m[10];
2403 r_view.frustum[4].dist = m[15] - m[14];
2405 r_view.frustum[5].normal[0] = m[3] + m[2];
2406 r_view.frustum[5].normal[1] = m[7] + m[6];
2407 r_view.frustum[5].normal[2] = m[11] + m[10];
2408 r_view.frustum[5].dist = m[15] + m[14];
2411 if (r_view.useperspective)
2413 slopex = 1.0 / r_view.frustum_x;
2414 slopey = 1.0 / r_view.frustum_y;
2415 VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
2416 VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
2417 VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
2418 VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
2419 VectorCopy(r_view.forward, r_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_view.frustum[0].normal);
2425 VectorNormalize(r_view.frustum[1].normal);
2426 VectorNormalize(r_view.frustum[2].normal);
2427 VectorNormalize(r_view.frustum[3].normal);
2429 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2430 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
2431 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
2432 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
2433 VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
2435 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
2436 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
2437 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
2438 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
2439 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2443 VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
2444 VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
2445 VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
2446 VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
2447 VectorCopy(r_view.forward, r_view.frustum[4].normal);
2448 r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
2449 r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
2450 r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
2451 r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
2452 r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
2454 r_view.numfrustumplanes = 5;
2456 if (r_view.useclipplane)
2458 r_view.numfrustumplanes = 6;
2459 r_view.frustum[5] = r_view.clipplane;
2462 for (i = 0;i < r_view.numfrustumplanes;i++)
2463 PlaneClassify(r_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_view.frustum[0].normal, r_view.up, r_view.forward, -(90 - r_refdef.fov_x / 2));
2471 //r_view.frustum[0].dist = DotProduct (r_view.origin, frustum[0].normal);
2472 //PlaneClassify(&frustum[0]);
2474 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2475 //RotatePointAroundVector( r_view.frustum[1].normal, r_view.up, r_view.forward, (90 - r_refdef.fov_x / 2));
2476 //r_view.frustum[1].dist = DotProduct (r_view.origin, frustum[1].normal);
2477 //PlaneClassify(&frustum[1]);
2479 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2480 //RotatePointAroundVector( r_view.frustum[2].normal, r_view.left, r_view.forward, -(90 - r_refdef.fov_y / 2));
2481 //r_view.frustum[2].dist = DotProduct (r_view.origin, frustum[2].normal);
2482 //PlaneClassify(&frustum[2]);
2484 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2485 //RotatePointAroundVector( r_view.frustum[3].normal, r_view.left, r_view.forward, (90 - r_refdef.fov_y / 2));
2486 //r_view.frustum[3].dist = DotProduct (r_view.origin, frustum[3].normal);
2487 //PlaneClassify(&frustum[3]);
2490 //VectorCopy(r_view.forward, r_view.frustum[4].normal);
2491 //r_view.frustum[4].dist = DotProduct (r_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_view.useclipplane);
2499 R_View_UpdateEntityVisible();
2502 void R_SetupView(void)
2504 if (!r_view.useperspective)
2505 GL_SetupView_Mode_Ortho(-r_view.ortho_x, -r_view.ortho_y, r_view.ortho_x, r_view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
2506 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2507 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
2509 GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2511 GL_SetupView_Orientation_FromEntity(&r_view.matrix);
2513 if (r_view.useclipplane)
2515 // LordHavoc: couldn't figure out how to make this approach the
2516 vec_t dist = r_view.clipplane.dist - r_water_clippingplanebias.value;
2517 vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
2518 if (viewdist < r_view.clipplane.dist + r_water_clippingplanebias.value)
2519 dist = r_view.clipplane.dist;
2520 GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_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_view.y is top to bottom
2534 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2535 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2536 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2537 GL_Color(1, 1, 1, 1);
2538 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_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_view.y is top to bottom
2567 qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2569 GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
2570 GL_Color(1, 1, 1, 1);
2571 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_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_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_view.width * r_water_resolutionmultiplier.value, r_view.width);
2662 waterheight = (int)bound(1, r_view.height * r_water_resolutionmultiplier.value, r_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_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_view_t originalview;
2777 r_waterstate_waterplane_t *p;
2779 originalview = r_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_view.showdebug = false;
2805 r_view.width = r_waterstate.waterwidth;
2806 r_view.height = r_waterstate.waterheight;
2807 r_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_view.clipplane = p->plane;
2815 VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
2816 r_view.clipplane.dist = -r_view.clipplane.dist;
2817 PlaneClassify(&r_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_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2828 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2830 // render reflected scene and copy into texture
2831 Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2832 r_view.clipplane = p->plane;
2833 // reverse the cullface settings for this render
2834 r_view.cullface_front = GL_FRONT;
2835 r_view.cullface_back = GL_BACK;
2836 if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
2838 r_view.usecustompvs = true;
2840 memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
2842 memset(r_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_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2857 R_ResetViewRendering3D();
2858 R_ClearScreen(r_refdef.fogenabled);
2859 if (r_timereport_active)
2860 R_TimeReport("viewclear");
2863 r_view = originalview;
2864 r_view.clear = true;
2865 r_waterstate.renderingscene = false;
2869 r_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_view.width);
2883 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_view.height / r_view.width;
2884 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_view.height);
2886 // calculate desired texture sizes
2887 if (gl_support_arb_texture_non_power_of_two)
2889 screentexturewidth = r_view.width;
2890 screentextureheight = r_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_view.height / (float)r_bloomstate.screentextureheight;
2956 r_bloomstate.screentexcoord2f[2] = (float)r_view.width / (float)r_bloomstate.screentexturewidth;
2957 r_bloomstate.screentexcoord2f[3] = (float)r_view.height / (float)r_bloomstate.screentextureheight;
2958 r_bloomstate.screentexcoord2f[4] = (float)r_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_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
2989 r_refdef.stats.bloom_copypixels += r_view.width * r_view.height;
2991 // now scale it down to the bloom texture size
2993 qglViewport(r_view.x, vid.height - (r_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_view.x, vid.height - (r_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_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
3015 r_refdef.stats.bloom_copypixels += r_view.width * r_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_view.x, vid.height - (r_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_view.x, vid.height - (r_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_view.x, vid.height - (r_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_view.x, vid.height - (r_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_view.colorscale;
3132 oldwidth = r_view.width;
3133 oldheight = r_view.height;
3134 r_view.width = r_bloomstate.bloomwidth;
3135 r_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_view.showdebug = false;
3142 r_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_view.showdebug = true;
3152 R_ResetViewRendering2D();
3154 R_Bloom_CopyHDRTexture();
3155 R_Bloom_MakeTexture();
3157 // restore the view settings
3158 r_view.width = oldwidth;
3159 r_view.height = oldheight;
3160 r_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_view.width * r_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_view.width * r_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_view.width * r_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 // color.rgb *= SceneBrightness;
3249 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3251 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
3252 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3253 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3254 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3256 VectorScale(fogvec, r_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_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_view.clear || r_refdef.fogenabled)
3373 R_ClearScreen(r_refdef.fogenabled);
3374 if (r_timereport_active)
3375 R_TimeReport("viewclear");
3377 r_view.clear = true;
3379 r_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)
3409 R_ResetViewRendering3D();
3412 if (r_timereport_active)
3413 R_TimeReport("watervis");
3415 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawAddWaterPlanes)
3417 r_refdef.worldmodel->DrawAddWaterPlanes(r_refdef.worldentity);
3418 if (r_timereport_active)
3419 R_TimeReport("waterworld");
3422 // don't let sound skip if going slow
3423 if (r_refdef.extraupdate)
3426 R_DrawModelsAddWaterPlanes();
3427 if (r_timereport_active)
3428 R_TimeReport("watermodels");
3430 R_Water_ProcessPlanes();
3431 if (r_timereport_active)
3432 R_TimeReport("waterscenes");
3435 R_ResetViewRendering3D();
3437 // don't let sound skip if going slow
3438 if (r_refdef.extraupdate)
3441 R_MeshQueue_BeginScene();
3446 if (r_timereport_active)
3447 R_TimeReport("visibility");
3449 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);
3451 if (cl.csqc_vidvars.drawworld)
3453 // don't let sound skip if going slow
3454 if (r_refdef.extraupdate)
3457 if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
3459 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
3460 if (r_timereport_active)
3461 R_TimeReport("worldsky");
3464 if (R_DrawBrushModelsSky() && r_timereport_active)
3465 R_TimeReport("bmodelsky");
3468 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->DrawDepth)
3470 r_refdef.worldmodel->DrawDepth(r_refdef.worldentity);
3471 if (r_timereport_active)
3472 R_TimeReport("worlddepth");
3474 if (r_depthfirst.integer >= 2)
3476 R_DrawModelsDepth();
3477 if (r_timereport_active)
3478 R_TimeReport("modeldepth");
3481 if (cl.csqc_vidvars.drawworld && r_refdef.worldmodel && r_refdef.worldmodel->Draw)
3483 r_refdef.worldmodel->Draw(r_refdef.worldentity);
3484 if (r_timereport_active)
3485 R_TimeReport("world");
3488 // don't let sound skip if going slow
3489 if (r_refdef.extraupdate)
3493 if (r_timereport_active)
3494 R_TimeReport("models");
3496 // don't let sound skip if going slow
3497 if (r_refdef.extraupdate)
3500 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3502 R_DrawModelShadows();
3504 R_ResetViewRendering3D();
3506 // don't let sound skip if going slow
3507 if (r_refdef.extraupdate)
3511 R_ShadowVolumeLighting(false);
3512 if (r_timereport_active)
3513 R_TimeReport("rtlights");
3515 // don't let sound skip if going slow
3516 if (r_refdef.extraupdate)
3519 if (cl.csqc_vidvars.drawworld)
3521 R_DrawLightningBeams();
3522 if (r_timereport_active)
3523 R_TimeReport("lightning");
3526 if (r_timereport_active)
3527 R_TimeReport("decals");
3530 if (r_timereport_active)
3531 R_TimeReport("particles");
3534 if (r_timereport_active)
3535 R_TimeReport("explosions");
3538 if (gl_support_fragment_shader)
3540 qglUseProgramObjectARB(0);CHECKGLERROR
3542 VM_CL_AddPolygonsToMeshQueue();
3544 if (r_view.showdebug)
3546 if (cl_locs_show.integer)
3549 if (r_timereport_active)
3550 R_TimeReport("showlocs");
3553 if (r_drawportals.integer)
3556 if (r_timereport_active)
3557 R_TimeReport("portals");
3560 if (r_showbboxes.value > 0)
3562 R_DrawEntityBBoxes();
3563 if (r_timereport_active)
3564 R_TimeReport("bboxes");
3568 if (gl_support_fragment_shader)
3570 qglUseProgramObjectARB(0);CHECKGLERROR
3572 R_MeshQueue_RenderTransparent();
3573 if (r_timereport_active)
3574 R_TimeReport("drawtrans");
3576 if (gl_support_fragment_shader)
3578 qglUseProgramObjectARB(0);CHECKGLERROR
3581 if (r_view.showdebug && r_refdef.worldmodel && r_refdef.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3583 r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
3584 if (r_timereport_active)
3585 R_TimeReport("worlddebug");
3586 R_DrawModelsDebug();
3587 if (r_timereport_active)
3588 R_TimeReport("modeldebug");
3591 if (gl_support_fragment_shader)
3593 qglUseProgramObjectARB(0);CHECKGLERROR
3596 if (cl.csqc_vidvars.drawworld)
3599 if (r_timereport_active)
3600 R_TimeReport("coronas");
3603 // don't let sound skip if going slow
3604 if (r_refdef.extraupdate)
3607 R_ResetViewRendering2D();
3610 static const int bboxelements[36] =
3620 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3623 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3624 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3625 GL_DepthMask(false);
3626 GL_DepthRange(0, 1);
3627 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3628 R_Mesh_Matrix(&identitymatrix);
3629 R_Mesh_ResetTextureState();
3631 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3632 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3633 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3634 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3635 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3636 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3637 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3638 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3639 R_FillColors(color4f, 8, cr, cg, cb, ca);
3640 if (r_refdef.fogenabled)
3642 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3644 f1 = FogPoint_World(v);
3646 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3647 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3648 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3651 R_Mesh_VertexPointer(vertex3f, 0, 0);
3652 R_Mesh_ColorPointer(color4f, 0, 0);
3653 R_Mesh_ResetTextureState();
3654 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3657 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3661 prvm_edict_t *edict;
3662 // this function draws bounding boxes of server entities
3666 for (i = 0;i < numsurfaces;i++)
3668 edict = PRVM_EDICT_NUM(surfacelist[i]);
3669 switch ((int)edict->fields.server->solid)
3671 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3672 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3673 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3674 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3675 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3676 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3678 color[3] *= r_showbboxes.value;
3679 color[3] = bound(0, color[3], 1);
3680 GL_DepthTest(!r_showdisabledepthtest.integer);
3681 GL_CullFace(r_view.cullface_front);
3682 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3687 static void R_DrawEntityBBoxes(void)
3690 prvm_edict_t *edict;
3692 // this function draws bounding boxes of server entities
3696 for (i = 0;i < prog->num_edicts;i++)
3698 edict = PRVM_EDICT_NUM(i);
3699 if (edict->priv.server->free)
3701 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3702 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3707 int nomodelelements[24] =
3719 float nomodelvertex3f[6*3] =
3729 float nomodelcolor4f[6*4] =
3731 0.0f, 0.0f, 0.5f, 1.0f,
3732 0.0f, 0.0f, 0.5f, 1.0f,
3733 0.0f, 0.5f, 0.0f, 1.0f,
3734 0.0f, 0.5f, 0.0f, 1.0f,
3735 0.5f, 0.0f, 0.0f, 1.0f,
3736 0.5f, 0.0f, 0.0f, 1.0f
3739 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3744 // this is only called once per entity so numsurfaces is always 1, and
3745 // surfacelist is always {0}, so this code does not handle batches
3746 R_Mesh_Matrix(&ent->matrix);
3748 if (ent->flags & EF_ADDITIVE)
3750 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3751 GL_DepthMask(false);
3753 else if (ent->alpha < 1)
3755 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3756 GL_DepthMask(false);
3760 GL_BlendFunc(GL_ONE, GL_ZERO);
3763 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3764 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3765 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3766 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_view.cullface_back);
3767 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3768 if (r_refdef.fogenabled)
3771 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3772 R_Mesh_ColorPointer(color4f, 0, 0);
3773 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3774 f1 = FogPoint_World(org);
3776 for (i = 0, c = color4f;i < 6;i++, c += 4)
3778 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
3779 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
3780 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
3784 else if (ent->alpha != 1)
3786 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3787 R_Mesh_ColorPointer(color4f, 0, 0);
3788 for (i = 0, c = color4f;i < 6;i++, c += 4)
3792 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
3793 R_Mesh_ResetTextureState();
3794 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
3797 void R_DrawNoModel(entity_render_t *ent)
3800 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3801 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
3802 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
3804 // R_DrawNoModelCallback(ent, 0);
3807 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
3809 vec3_t right1, right2, diff, normal;
3811 VectorSubtract (org2, org1, normal);
3813 // calculate 'right' vector for start
3814 VectorSubtract (r_view.origin, org1, diff);
3815 CrossProduct (normal, diff, right1);
3816 VectorNormalize (right1);
3818 // calculate 'right' vector for end
3819 VectorSubtract (r_view.origin, org2, diff);
3820 CrossProduct (normal, diff, right2);
3821 VectorNormalize (right2);
3823 vert[ 0] = org1[0] + width * right1[0];
3824 vert[ 1] = org1[1] + width * right1[1];
3825 vert[ 2] = org1[2] + width * right1[2];
3826 vert[ 3] = org1[0] - width * right1[0];
3827 vert[ 4] = org1[1] - width * right1[1];
3828 vert[ 5] = org1[2] - width * right1[2];
3829 vert[ 6] = org2[0] - width * right2[0];
3830 vert[ 7] = org2[1] - width * right2[1];
3831 vert[ 8] = org2[2] - width * right2[2];
3832 vert[ 9] = org2[0] + width * right2[0];
3833 vert[10] = org2[1] + width * right2[1];
3834 vert[11] = org2[2] + width * right2[2];
3837 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
3839 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)
3844 if (r_refdef.fogenabled)
3845 fog = FogPoint_World(origin);
3847 R_Mesh_Matrix(&identitymatrix);
3848 GL_BlendFunc(blendfunc1, blendfunc2);
3854 GL_CullFace(r_view.cullface_front);
3857 GL_CullFace(r_view.cullface_back);
3859 GL_DepthMask(false);
3860 GL_DepthRange(0, depthshort ? 0.0625 : 1);
3861 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3862 GL_DepthTest(!depthdisable);
3864 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
3865 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
3866 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
3867 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
3868 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
3869 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
3870 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
3871 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
3872 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
3873 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
3874 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
3875 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
3877 R_Mesh_VertexPointer(vertex3f, 0, 0);
3878 R_Mesh_ColorPointer(NULL, 0, 0);
3879 R_Mesh_ResetTextureState();
3880 R_Mesh_TexBind(0, R_GetTexture(texture));
3881 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
3882 // FIXME: fixed function path can't properly handle r_view.colorscale > 1
3883 GL_Color(cr * fog * r_view.colorscale, cg * fog * r_view.colorscale, cb * fog * r_view.colorscale, ca);
3884 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3886 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
3888 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
3889 GL_BlendFunc(blendfunc1, GL_ONE);
3891 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
3892 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3896 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
3901 VectorSet(v, x, y, z);
3902 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
3903 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
3905 if (i == mesh->numvertices)
3907 if (mesh->numvertices < mesh->maxvertices)
3909 VectorCopy(v, vertex3f);
3910 mesh->numvertices++;
3912 return mesh->numvertices;
3918 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
3922 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3923 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
3924 e = mesh->element3i + mesh->numtriangles * 3;
3925 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
3927 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
3928 if (mesh->numtriangles < mesh->maxtriangles)
3933 mesh->numtriangles++;
3935 element[1] = element[2];
3939 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
3943 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3944 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
3945 e = mesh->element3i + mesh->numtriangles * 3;
3946 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
3948 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
3949 if (mesh->numtriangles < mesh->maxtriangles)
3954 mesh->numtriangles++;
3956 element[1] = element[2];
3960 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
3961 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
3963 int planenum, planenum2;
3966 mplane_t *plane, *plane2;
3968 double temppoints[2][256*3];
3969 // figure out how large a bounding box we need to properly compute this brush
3971 for (w = 0;w < numplanes;w++)
3972 maxdist = max(maxdist, planes[w].dist);
3973 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
3974 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
3975 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
3979 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
3980 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
3982 if (planenum2 == planenum)
3984 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);
3987 if (tempnumpoints < 3)
3989 // generate elements forming a triangle fan for this polygon
3990 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
3994 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)
3996 texturelayer_t *layer;
3997 layer = t->currentlayers + t->currentnumlayers++;
3999 layer->depthmask = depthmask;
4000 layer->blendfunc1 = blendfunc1;
4001 layer->blendfunc2 = blendfunc2;
4002 layer->texture = texture;
4003 layer->texmatrix = *matrix;
4004 layer->color[0] = r * r_view.colorscale;
4005 layer->color[1] = g * r_view.colorscale;
4006 layer->color[2] = b * r_view.colorscale;
4007 layer->color[3] = a;
4010 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4013 index = parms[2] + r_refdef.time * parms[3];
4014 index -= floor(index);
4018 case Q3WAVEFUNC_NONE:
4019 case Q3WAVEFUNC_NOISE:
4020 case Q3WAVEFUNC_COUNT:
4023 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4024 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4025 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4026 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4027 case Q3WAVEFUNC_TRIANGLE:
4029 f = index - floor(index);
4040 return (float)(parms[0] + parms[1] * f);
4043 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4046 model_t *model = ent->model;
4049 q3shaderinfo_layer_tcmod_t *tcmod;
4051 // switch to an alternate material if this is a q1bsp animated material
4053 texture_t *texture = t;
4054 int s = ent->skinnum;
4055 if ((unsigned int)s >= (unsigned int)model->numskins)
4057 if (model->skinscenes)
4059 if (model->skinscenes[s].framecount > 1)
4060 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4062 s = model->skinscenes[s].firstframe;
4065 t = t + s * model->num_surfaces;
4068 // use an alternate animation if the entity's frame is not 0,
4069 // and only if the texture has an alternate animation
4070 if (ent->frame2 != 0 && t->anim_total[1])
4071 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[1]) : 0];
4073 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[0]) : 0];
4075 texture->currentframe = t;
4078 // update currentskinframe to be a qw skin or animation frame
4079 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4081 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4083 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4084 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4085 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);
4087 t->currentskinframe = r_qwskincache_skinframe[i];
4088 if (t->currentskinframe == NULL)
4089 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4091 else if (t->numskinframes >= 2)
4092 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4093 if (t->backgroundnumskinframes >= 2)
4094 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4096 t->currentmaterialflags = t->basematerialflags;
4097 t->currentalpha = ent->alpha;
4098 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4100 t->currentalpha *= r_wateralpha.value;
4102 * FIXME what is this supposed to do?
4103 // if rendering refraction/reflection, disable transparency
4104 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4105 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4108 if(!r_waterstate.enabled)
4109 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4110 if (!(ent->flags & RENDER_LIGHT))
4111 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4112 else if (rsurface.modeltexcoordlightmap2f == NULL)
4114 // pick a model lighting mode
4115 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4116 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4118 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4120 if (ent->effects & EF_ADDITIVE)
4121 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4122 else if (t->currentalpha < 1)
4123 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4124 if (ent->effects & EF_DOUBLESIDED)
4125 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4126 if (ent->effects & EF_NODEPTHTEST)
4127 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4128 if (ent->flags & RENDER_VIEWMODEL)
4129 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4130 if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
4131 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4133 // make sure that the waterscroll matrix is used on water surfaces when
4134 // there is no tcmod
4135 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4136 t->currenttexmatrix = r_waterscrollmatrix;
4138 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4141 switch(tcmod->tcmod)
4145 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4146 matrix = r_waterscrollmatrix;
4148 matrix = identitymatrix;
4150 case Q3TCMOD_ENTITYTRANSLATE:
4151 // this is used in Q3 to allow the gamecode to control texcoord
4152 // scrolling on the entity, which is not supported in darkplaces yet.
4153 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4155 case Q3TCMOD_ROTATE:
4156 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4157 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.time, 0, 0, 1);
4158 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4161 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4163 case Q3TCMOD_SCROLL:
4164 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.time, tcmod->parms[1] * r_refdef.time, 0);
4166 case Q3TCMOD_STRETCH:
4167 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4168 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4170 case Q3TCMOD_TRANSFORM:
4171 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4172 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4173 VectorSet(tcmat + 6, 0 , 0 , 1);
4174 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4175 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4177 case Q3TCMOD_TURBULENT:
4178 // this is handled in the RSurf_PrepareVertices function
4179 matrix = identitymatrix;
4182 // either replace or concatenate the transformation
4184 t->currenttexmatrix = matrix;
4187 matrix4x4_t temp = t->currenttexmatrix;
4188 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4192 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4193 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4194 t->glosstexture = r_texture_black;
4195 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4196 t->backgroundglosstexture = r_texture_black;
4197 t->specularpower = r_shadow_glossexponent.value;
4198 // TODO: store reference values for these in the texture?
4199 t->specularscale = 0;
4200 if (r_shadow_gloss.integer > 0)
4202 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4204 if (r_shadow_glossintensity.value > 0)
4206 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4207 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4208 t->specularscale = r_shadow_glossintensity.value;
4211 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4213 t->glosstexture = r_texture_white;
4214 t->backgroundglosstexture = r_texture_white;
4215 t->specularscale = r_shadow_gloss2intensity.value;
4219 // lightmaps mode looks bad with dlights using actual texturing, so turn
4220 // off the colormap and glossmap, but leave the normalmap on as it still
4221 // accurately represents the shading involved
4222 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4224 t->basetexture = r_texture_white;
4225 t->specularscale = 0;
4228 VectorClear(t->dlightcolor);
4229 t->currentnumlayers = 0;
4230 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4232 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4234 int blendfunc1, blendfunc2, depthmask;
4235 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4237 blendfunc1 = GL_SRC_ALPHA;
4238 blendfunc2 = GL_ONE;
4240 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4242 blendfunc1 = GL_SRC_ALPHA;
4243 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4245 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4247 blendfunc1 = t->customblendfunc[0];
4248 blendfunc2 = t->customblendfunc[1];
4252 blendfunc1 = GL_ONE;
4253 blendfunc2 = GL_ZERO;
4255 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4256 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4258 rtexture_t *currentbasetexture;
4260 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4261 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4262 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4263 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4265 // fullbright is not affected by r_refdef.lightmapintensity
4266 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4267 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4268 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0], ent->colormap_pantscolor[1] * ent->colormod[1], ent->colormap_pantscolor[2] * ent->colormod[2], t->currentalpha);
4269 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4270 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0], ent->colormap_shirtcolor[1] * ent->colormod[1], ent->colormap_shirtcolor[2] * ent->colormod[2], t->currentalpha);
4275 // set the color tint used for lights affecting this surface
4276 VectorSet(t->dlightcolor, ent->colormod[0] * t->currentalpha, ent->colormod[1] * t->currentalpha, ent->colormod[2] * t->currentalpha);
4278 // q3bsp has no lightmap updates, so the lightstylevalue that
4279 // would normally be baked into the lightmap must be
4280 // applied to the color
4281 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4282 if (ent->model->type == mod_brushq3)
4283 colorscale *= r_refdef.rtlightstylevalue[0];
4284 colorscale *= r_refdef.lightmapintensity;
4285 Vector4Set(t->lightmapcolor, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
4286 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * colorscale, ent->colormod[1] * colorscale, ent->colormod[2] * colorscale, t->currentalpha);
4287 if (r_ambient.value >= (1.0f/64.0f))
4288 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
4289 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4291 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * colorscale, ent->colormap_pantscolor[1] * ent->colormod[1] * colorscale, ent->colormap_pantscolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
4292 if (r_ambient.value >= (1.0f/64.0f))
4293 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_pantscolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
4295 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4297 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * colorscale, ent->colormap_shirtcolor[1] * ent->colormod[1] * colorscale, ent->colormap_shirtcolor[2] * ent->colormod[2] * colorscale, t->currentalpha);
4298 if (r_ambient.value >= (1.0f/64.0f))
4299 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ent->colormod[0] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[1] * ent->colormod[1] * r_ambient.value * (1.0f / 64.0f), ent->colormap_shirtcolor[2] * ent->colormod[2] * r_ambient.value * (1.0f / 64.0f), t->currentalpha);
4302 if (t->currentskinframe->glow != NULL)
4303 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->currentalpha);
4304 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4306 // if this is opaque use alpha blend which will darken the earlier
4309 // if this is an alpha blended material, all the earlier passes
4310 // were darkened by fog already, so we only need to add the fog
4311 // color ontop through the fog mask texture
4313 // if this is an additive blended material, all the earlier passes
4314 // were darkened by fog already, and we should not add fog color
4315 // (because the background was not darkened, there is no fog color
4316 // that was lost behind it).
4317 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_view.colorscale, r_refdef.fogcolor[1] / r_view.colorscale, r_refdef.fogcolor[2] / r_view.colorscale, t->currentalpha);
4324 void R_UpdateAllTextureInfo(entity_render_t *ent)
4328 for (i = 0;i < ent->model->num_texturesperskin;i++)
4329 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4332 rsurfacestate_t rsurface;
4334 void R_Mesh_ResizeArrays(int newvertices)
4337 if (rsurface.array_size >= newvertices)
4339 if (rsurface.array_modelvertex3f)
4340 Mem_Free(rsurface.array_modelvertex3f);
4341 rsurface.array_size = (newvertices + 1023) & ~1023;
4342 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4343 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4344 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4345 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4346 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4347 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4348 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4349 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4350 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4351 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4352 rsurface.array_color4f = base + rsurface.array_size * 27;
4353 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4356 void RSurf_CleanUp(void)
4359 if (rsurface.mode == RSURFMODE_GLSL)
4361 qglUseProgramObjectARB(0);CHECKGLERROR
4363 GL_AlphaTest(false);
4364 rsurface.mode = RSURFMODE_NONE;
4365 rsurface.uselightmaptexture = false;
4366 rsurface.texture = NULL;
4369 void RSurf_ActiveWorldEntity(void)
4371 model_t *model = r_refdef.worldmodel;
4373 if (rsurface.array_size < model->surfmesh.num_vertices)
4374 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4375 rsurface.matrix = identitymatrix;
4376 rsurface.inversematrix = identitymatrix;
4377 R_Mesh_Matrix(&identitymatrix);
4378 VectorCopy(r_view.origin, rsurface.modelorg);
4379 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4380 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4381 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4382 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4383 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4384 rsurface.frameblend[0].frame = 0;
4385 rsurface.frameblend[0].lerp = 1;
4386 rsurface.frameblend[1].frame = 0;
4387 rsurface.frameblend[1].lerp = 0;
4388 rsurface.frameblend[2].frame = 0;
4389 rsurface.frameblend[2].lerp = 0;
4390 rsurface.frameblend[3].frame = 0;
4391 rsurface.frameblend[3].lerp = 0;
4392 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4393 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4394 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4395 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4396 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4397 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4398 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4399 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4400 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4401 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4402 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4403 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4404 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4405 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4406 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4407 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4408 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4409 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4410 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4411 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4412 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4413 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4414 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4415 rsurface.modelelement3i = model->surfmesh.data_element3i;
4416 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4417 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4418 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4419 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4420 rsurface.modelsurfaces = model->data_surfaces;
4421 rsurface.generatedvertex = false;
4422 rsurface.vertex3f = rsurface.modelvertex3f;
4423 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4424 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4425 rsurface.svector3f = rsurface.modelsvector3f;
4426 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4427 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4428 rsurface.tvector3f = rsurface.modeltvector3f;
4429 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4430 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4431 rsurface.normal3f = rsurface.modelnormal3f;
4432 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4433 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4434 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4437 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4439 model_t *model = ent->model;
4441 if (rsurface.array_size < model->surfmesh.num_vertices)
4442 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4443 rsurface.matrix = ent->matrix;
4444 rsurface.inversematrix = ent->inversematrix;
4445 R_Mesh_Matrix(&rsurface.matrix);
4446 Matrix4x4_Transform(&rsurface.inversematrix, r_view.origin, rsurface.modelorg);
4447 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4448 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4449 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4450 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4451 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4452 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4453 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4454 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4455 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4456 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4457 rsurface.frameblend[0] = ent->frameblend[0];
4458 rsurface.frameblend[1] = ent->frameblend[1];
4459 rsurface.frameblend[2] = ent->frameblend[2];
4460 rsurface.frameblend[3] = ent->frameblend[3];
4461 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4462 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4463 if (ent->model->brush.submodel)
4465 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4466 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4468 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4472 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4473 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4474 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4475 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4476 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4478 else if (wantnormals)
4480 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4481 rsurface.modelsvector3f = NULL;
4482 rsurface.modeltvector3f = NULL;
4483 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4484 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4488 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4489 rsurface.modelsvector3f = NULL;
4490 rsurface.modeltvector3f = NULL;
4491 rsurface.modelnormal3f = NULL;
4492 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4494 rsurface.modelvertex3f_bufferobject = 0;
4495 rsurface.modelvertex3f_bufferoffset = 0;
4496 rsurface.modelsvector3f_bufferobject = 0;
4497 rsurface.modelsvector3f_bufferoffset = 0;
4498 rsurface.modeltvector3f_bufferobject = 0;
4499 rsurface.modeltvector3f_bufferoffset = 0;
4500 rsurface.modelnormal3f_bufferobject = 0;
4501 rsurface.modelnormal3f_bufferoffset = 0;
4502 rsurface.generatedvertex = true;
4506 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4507 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4508 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4509 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4510 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4511 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4512 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4513 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4514 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4515 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4516 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4517 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4518 rsurface.generatedvertex = false;
4520 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4521 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4522 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4523 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4524 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4525 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4526 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4527 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4528 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4529 rsurface.modelelement3i = model->surfmesh.data_element3i;
4530 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4531 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4532 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4533 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4534 rsurface.modelsurfaces = model->data_surfaces;
4535 rsurface.vertex3f = rsurface.modelvertex3f;
4536 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4537 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4538 rsurface.svector3f = rsurface.modelsvector3f;
4539 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4540 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4541 rsurface.tvector3f = rsurface.modeltvector3f;
4542 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4543 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4544 rsurface.normal3f = rsurface.modelnormal3f;
4545 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4546 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4547 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4550 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4551 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4554 int texturesurfaceindex;
4559 const float *v1, *in_tc;
4561 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4563 q3shaderinfo_deform_t *deform;
4564 // 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
4565 if (rsurface.generatedvertex)
4567 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4568 generatenormals = true;
4569 for (i = 0;i < Q3MAXDEFORMS;i++)
4571 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4573 generatetangents = true;
4574 generatenormals = true;
4576 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4577 generatenormals = true;
4579 if (generatenormals && !rsurface.modelnormal3f)
4581 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4582 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4583 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4584 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4586 if (generatetangents && !rsurface.modelsvector3f)
4588 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4589 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4590 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4591 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4592 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4593 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4594 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);
4597 rsurface.vertex3f = rsurface.modelvertex3f;
4598 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4599 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4600 rsurface.svector3f = rsurface.modelsvector3f;
4601 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4602 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4603 rsurface.tvector3f = rsurface.modeltvector3f;
4604 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4605 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4606 rsurface.normal3f = rsurface.modelnormal3f;
4607 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4608 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4609 // if vertices are deformed (sprite flares and things in maps, possibly
4610 // water waves, bulges and other deformations), generate them into
4611 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4612 // (may be static model data or generated data for an animated model, or
4613 // the previous deform pass)
4614 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4616 switch (deform->deform)
4619 case Q3DEFORM_PROJECTIONSHADOW:
4620 case Q3DEFORM_TEXT0:
4621 case Q3DEFORM_TEXT1:
4622 case Q3DEFORM_TEXT2:
4623 case Q3DEFORM_TEXT3:
4624 case Q3DEFORM_TEXT4:
4625 case Q3DEFORM_TEXT5:
4626 case Q3DEFORM_TEXT6:
4627 case Q3DEFORM_TEXT7:
4630 case Q3DEFORM_AUTOSPRITE:
4631 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4632 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4633 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4634 VectorNormalize(newforward);
4635 VectorNormalize(newright);
4636 VectorNormalize(newup);
4637 // make deformed versions of only the model vertices used by the specified surfaces
4638 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4640 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4641 // a single autosprite surface can contain multiple sprites...
4642 for (j = 0;j < surface->num_vertices - 3;j += 4)
4644 VectorClear(center);
4645 for (i = 0;i < 4;i++)
4646 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4647 VectorScale(center, 0.25f, center);
4648 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4649 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4650 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4651 for (i = 0;i < 4;i++)
4653 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4654 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4657 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);
4658 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);
4660 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4661 rsurface.vertex3f_bufferobject = 0;
4662 rsurface.vertex3f_bufferoffset = 0;
4663 rsurface.svector3f = rsurface.array_deformedsvector3f;
4664 rsurface.svector3f_bufferobject = 0;
4665 rsurface.svector3f_bufferoffset = 0;
4666 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4667 rsurface.tvector3f_bufferobject = 0;
4668 rsurface.tvector3f_bufferoffset = 0;
4669 rsurface.normal3f = rsurface.array_deformednormal3f;
4670 rsurface.normal3f_bufferobject = 0;
4671 rsurface.normal3f_bufferoffset = 0;
4673 case Q3DEFORM_AUTOSPRITE2:
4674 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, newforward);
4675 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.right, newright);
4676 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.up, newup);
4677 VectorNormalize(newforward);
4678 VectorNormalize(newright);
4679 VectorNormalize(newup);
4680 // make deformed versions of only the model vertices used by the specified surfaces
4681 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4683 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4684 const float *v1, *v2;
4694 memset(shortest, 0, sizeof(shortest));
4695 // a single autosprite surface can contain multiple sprites...
4696 for (j = 0;j < surface->num_vertices - 3;j += 4)
4698 VectorClear(center);
4699 for (i = 0;i < 4;i++)
4700 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4701 VectorScale(center, 0.25f, center);
4702 // find the two shortest edges, then use them to define the
4703 // axis vectors for rotating around the central axis
4704 for (i = 0;i < 6;i++)
4706 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4707 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4709 Debug_PolygonBegin(NULL, 0, false, 0);
4710 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4711 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);
4712 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4715 l = VectorDistance2(v1, v2);
4716 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4718 l += (1.0f / 1024.0f);
4719 if (shortest[0].length2 > l || i == 0)
4721 shortest[1] = shortest[0];
4722 shortest[0].length2 = l;
4723 shortest[0].v1 = v1;
4724 shortest[0].v2 = v2;
4726 else if (shortest[1].length2 > l || i == 1)
4728 shortest[1].length2 = l;
4729 shortest[1].v1 = v1;
4730 shortest[1].v2 = v2;
4733 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4734 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4736 Debug_PolygonBegin(NULL, 0, false, 0);
4737 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4738 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);
4739 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4742 // this calculates the right vector from the shortest edge
4743 // and the up vector from the edge midpoints
4744 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4745 VectorNormalize(right);
4746 VectorSubtract(end, start, up);
4747 VectorNormalize(up);
4748 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4749 //VectorSubtract(rsurface.modelorg, center, forward);
4750 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_view.forward, forward);
4751 VectorNegate(forward, forward);
4752 VectorReflect(forward, 0, up, forward);
4753 VectorNormalize(forward);
4754 CrossProduct(up, forward, newright);
4755 VectorNormalize(newright);
4757 Debug_PolygonBegin(NULL, 0, false, 0);
4758 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);
4759 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4760 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4764 Debug_PolygonBegin(NULL, 0, false, 0);
4765 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4766 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4767 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4770 // rotate the quad around the up axis vector, this is made
4771 // especially easy by the fact we know the quad is flat,
4772 // so we only have to subtract the center position and
4773 // measure distance along the right vector, and then
4774 // multiply that by the newright vector and add back the
4776 // we also need to subtract the old position to undo the
4777 // displacement from the center, which we do with a
4778 // DotProduct, the subtraction/addition of center is also
4779 // optimized into DotProducts here
4780 l = DotProduct(right, center);
4781 for (i = 0;i < 4;i++)
4783 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
4784 f = DotProduct(right, v1) - l;
4785 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4788 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);
4789 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);
4791 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4792 rsurface.vertex3f_bufferobject = 0;
4793 rsurface.vertex3f_bufferoffset = 0;
4794 rsurface.svector3f = rsurface.array_deformedsvector3f;
4795 rsurface.svector3f_bufferobject = 0;
4796 rsurface.svector3f_bufferoffset = 0;
4797 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4798 rsurface.tvector3f_bufferobject = 0;
4799 rsurface.tvector3f_bufferoffset = 0;
4800 rsurface.normal3f = rsurface.array_deformednormal3f;
4801 rsurface.normal3f_bufferobject = 0;
4802 rsurface.normal3f_bufferoffset = 0;
4804 case Q3DEFORM_NORMAL:
4805 // deform the normals to make reflections wavey
4806 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4808 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4809 for (j = 0;j < surface->num_vertices;j++)
4812 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
4813 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
4814 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
4815 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4816 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4817 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.time * deform->parms[1]);
4818 VectorNormalize(normal);
4820 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);
4822 rsurface.svector3f = rsurface.array_deformedsvector3f;
4823 rsurface.svector3f_bufferobject = 0;
4824 rsurface.svector3f_bufferoffset = 0;
4825 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4826 rsurface.tvector3f_bufferobject = 0;
4827 rsurface.tvector3f_bufferoffset = 0;
4828 rsurface.normal3f = rsurface.array_deformednormal3f;
4829 rsurface.normal3f_bufferobject = 0;
4830 rsurface.normal3f_bufferoffset = 0;
4833 // deform vertex array to make wavey water and flags and such
4834 waveparms[0] = deform->waveparms[0];
4835 waveparms[1] = deform->waveparms[1];
4836 waveparms[2] = deform->waveparms[2];
4837 waveparms[3] = deform->waveparms[3];
4838 // this is how a divisor of vertex influence on deformation
4839 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
4840 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4841 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4843 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4844 for (j = 0;j < surface->num_vertices;j++)
4846 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
4847 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
4848 // if the wavefunc depends on time, evaluate it per-vertex
4851 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
4852 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
4854 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
4857 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4858 rsurface.vertex3f_bufferobject = 0;
4859 rsurface.vertex3f_bufferoffset = 0;
4861 case Q3DEFORM_BULGE:
4862 // deform vertex array to make the surface have moving bulges
4863 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4865 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4866 for (j = 0;j < surface->num_vertices;j++)
4868 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.time * deform->parms[2])) * deform->parms[1];
4869 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4872 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4873 rsurface.vertex3f_bufferobject = 0;
4874 rsurface.vertex3f_bufferoffset = 0;
4877 // deform vertex array
4878 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
4879 VectorScale(deform->parms, scale, waveparms);
4880 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4882 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4883 for (j = 0;j < surface->num_vertices;j++)
4884 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
4886 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4887 rsurface.vertex3f_bufferobject = 0;
4888 rsurface.vertex3f_bufferoffset = 0;
4892 // generate texcoords based on the chosen texcoord source
4893 switch(rsurface.texture->tcgen.tcgen)
4896 case Q3TCGEN_TEXTURE:
4897 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4898 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
4899 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
4901 case Q3TCGEN_LIGHTMAP:
4902 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
4903 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4904 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4906 case Q3TCGEN_VECTOR:
4907 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4909 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4910 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)
4912 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
4913 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
4916 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4917 rsurface.texcoordtexture2f_bufferobject = 0;
4918 rsurface.texcoordtexture2f_bufferoffset = 0;
4920 case Q3TCGEN_ENVIRONMENT:
4921 // make environment reflections using a spheremap
4922 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4924 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4925 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
4926 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
4927 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
4928 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
4930 float l, d, eyedir[3];
4931 VectorSubtract(rsurface.modelorg, vertex, eyedir);
4932 l = 0.5f / VectorLength(eyedir);
4933 d = DotProduct(normal, eyedir)*2;
4934 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
4935 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
4938 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4939 rsurface.texcoordtexture2f_bufferobject = 0;
4940 rsurface.texcoordtexture2f_bufferoffset = 0;
4943 // the only tcmod that needs software vertex processing is turbulent, so
4944 // check for it here and apply the changes if needed
4945 // and we only support that as the first one
4946 // (handling a mixture of turbulent and other tcmods would be problematic
4947 // without punting it entirely to a software path)
4948 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
4950 amplitude = rsurface.texture->tcmods[0].parms[1];
4951 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.time * rsurface.texture->tcmods[0].parms[3];
4952 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4954 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4955 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)
4957 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4958 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
4961 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
4962 rsurface.texcoordtexture2f_bufferobject = 0;
4963 rsurface.texcoordtexture2f_bufferoffset = 0;
4965 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
4966 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
4967 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
4968 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
4971 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
4974 const msurface_t *surface = texturesurfacelist[0];
4975 const msurface_t *surface2;
4980 // TODO: lock all array ranges before render, rather than on each surface
4981 if (texturenumsurfaces == 1)
4983 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
4984 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));
4986 else if (r_batchmode.integer == 2)
4988 #define MAXBATCHTRIANGLES 4096
4989 int batchtriangles = 0;
4990 int batchelements[MAXBATCHTRIANGLES*3];
4991 for (i = 0;i < texturenumsurfaces;i = j)
4993 surface = texturesurfacelist[i];
4995 if (surface->num_triangles > MAXBATCHTRIANGLES)
4997 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));
5000 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5001 batchtriangles = surface->num_triangles;
5002 firstvertex = surface->num_firstvertex;
5003 endvertex = surface->num_firstvertex + surface->num_vertices;
5004 for (;j < texturenumsurfaces;j++)
5006 surface2 = texturesurfacelist[j];
5007 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5009 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5010 batchtriangles += surface2->num_triangles;
5011 firstvertex = min(firstvertex, surface2->num_firstvertex);
5012 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5014 surface2 = texturesurfacelist[j-1];
5015 numvertices = endvertex - firstvertex;
5016 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5019 else if (r_batchmode.integer == 1)
5021 for (i = 0;i < texturenumsurfaces;i = j)
5023 surface = texturesurfacelist[i];
5024 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5025 if (texturesurfacelist[j] != surface2)
5027 surface2 = texturesurfacelist[j-1];
5028 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5029 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5030 GL_LockArrays(surface->num_firstvertex, numvertices);
5031 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5036 for (i = 0;i < texturenumsurfaces;i++)
5038 surface = texturesurfacelist[i];
5039 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5040 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));
5045 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5047 int i, planeindex, vertexindex;
5051 r_waterstate_waterplane_t *p, *bestp;
5052 msurface_t *surface;
5053 if (r_waterstate.renderingscene)
5055 for (i = 0;i < texturenumsurfaces;i++)
5057 surface = texturesurfacelist[i];
5058 if (lightmaptexunit >= 0)
5059 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5060 if (deluxemaptexunit >= 0)
5061 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5062 // pick the closest matching water plane
5065 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5068 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5070 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5071 d += fabs(PlaneDiff(vert, &p->plane));
5073 if (bestd > d || !bestp)
5081 if (refractiontexunit >= 0)
5082 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5083 if (reflectiontexunit >= 0)
5084 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5088 if (refractiontexunit >= 0)
5089 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5090 if (reflectiontexunit >= 0)
5091 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5093 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5094 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));
5098 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5102 const msurface_t *surface = texturesurfacelist[0];
5103 const msurface_t *surface2;
5108 // TODO: lock all array ranges before render, rather than on each surface
5109 if (texturenumsurfaces == 1)
5111 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5112 if (deluxemaptexunit >= 0)
5113 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5114 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5115 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));
5117 else if (r_batchmode.integer == 2)
5119 #define MAXBATCHTRIANGLES 4096
5120 int batchtriangles = 0;
5121 int batchelements[MAXBATCHTRIANGLES*3];
5122 for (i = 0;i < texturenumsurfaces;i = j)
5124 surface = texturesurfacelist[i];
5125 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5126 if (deluxemaptexunit >= 0)
5127 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5129 if (surface->num_triangles > MAXBATCHTRIANGLES)
5131 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));
5134 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5135 batchtriangles = surface->num_triangles;
5136 firstvertex = surface->num_firstvertex;
5137 endvertex = surface->num_firstvertex + surface->num_vertices;
5138 for (;j < texturenumsurfaces;j++)
5140 surface2 = texturesurfacelist[j];
5141 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5143 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5144 batchtriangles += surface2->num_triangles;
5145 firstvertex = min(firstvertex, surface2->num_firstvertex);
5146 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5148 surface2 = texturesurfacelist[j-1];
5149 numvertices = endvertex - firstvertex;
5150 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5153 else if (r_batchmode.integer == 1)
5156 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5157 for (i = 0;i < texturenumsurfaces;i = j)
5159 surface = texturesurfacelist[i];
5160 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5161 if (texturesurfacelist[j] != surface2)
5163 Con_Printf(" %i", j - i);
5166 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5168 for (i = 0;i < texturenumsurfaces;i = j)
5170 surface = texturesurfacelist[i];
5171 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5172 if (deluxemaptexunit >= 0)
5173 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5174 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5175 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5178 Con_Printf(" %i", j - i);
5180 surface2 = texturesurfacelist[j-1];
5181 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5182 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5183 GL_LockArrays(surface->num_firstvertex, numvertices);
5184 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5192 for (i = 0;i < texturenumsurfaces;i++)
5194 surface = texturesurfacelist[i];
5195 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5196 if (deluxemaptexunit >= 0)
5197 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5198 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5199 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));
5204 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5207 int texturesurfaceindex;
5208 if (r_showsurfaces.integer == 2)
5210 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5212 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5213 for (j = 0;j < surface->num_triangles;j++)
5215 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_view.colorscale;
5216 GL_Color(f, f, f, 1);
5217 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)));
5223 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5225 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5226 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5227 GL_Color((k & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_view.colorscale, 1);
5228 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5229 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));
5234 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5236 int texturesurfaceindex;
5240 if (rsurface.lightmapcolor4f)
5242 // generate color arrays for the surfaces in this list
5243 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5245 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5246 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)
5248 f = FogPoint_Model(v);
5258 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5260 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5261 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)
5263 f = FogPoint_Model(v);
5271 rsurface.lightmapcolor4f = rsurface.array_color4f;
5272 rsurface.lightmapcolor4f_bufferobject = 0;
5273 rsurface.lightmapcolor4f_bufferoffset = 0;
5276 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5278 int texturesurfaceindex;
5281 if (!rsurface.lightmapcolor4f)
5283 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5285 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5286 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)
5294 rsurface.lightmapcolor4f = rsurface.array_color4f;
5295 rsurface.lightmapcolor4f_bufferobject = 0;
5296 rsurface.lightmapcolor4f_bufferoffset = 0;
5299 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5302 rsurface.lightmapcolor4f = NULL;
5303 rsurface.lightmapcolor4f_bufferobject = 0;
5304 rsurface.lightmapcolor4f_bufferoffset = 0;
5305 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5306 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5307 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5308 GL_Color(r, g, b, a);
5309 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5312 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5314 // TODO: optimize applyfog && applycolor case
5315 // just apply fog if necessary, and tint the fog color array if necessary
5316 rsurface.lightmapcolor4f = NULL;
5317 rsurface.lightmapcolor4f_bufferobject = 0;
5318 rsurface.lightmapcolor4f_bufferoffset = 0;
5319 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5320 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5321 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5322 GL_Color(r, g, b, a);
5323 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5326 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5328 int texturesurfaceindex;
5332 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5334 // generate color arrays for the surfaces in this list
5335 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5337 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5338 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5340 if (surface->lightmapinfo->samples)
5342 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5343 float scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5344 VectorScale(lm, scale, c);
5345 if (surface->lightmapinfo->styles[1] != 255)
5347 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5349 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5350 VectorMA(c, scale, lm, c);
5351 if (surface->lightmapinfo->styles[2] != 255)
5354 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5355 VectorMA(c, scale, lm, c);
5356 if (surface->lightmapinfo->styles[3] != 255)
5359 scale = r_refdef.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5360 VectorMA(c, scale, lm, c);
5370 rsurface.lightmapcolor4f = rsurface.array_color4f;
5371 rsurface.lightmapcolor4f_bufferobject = 0;
5372 rsurface.lightmapcolor4f_bufferoffset = 0;
5376 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5377 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5378 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5380 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5381 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5382 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5383 GL_Color(r, g, b, a);
5384 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5387 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5389 int texturesurfaceindex;
5393 vec3_t ambientcolor;
5394 vec3_t diffusecolor;
5398 VectorCopy(rsurface.modellight_lightdir, lightdir);
5399 f = 0.5f * r_refdef.lightmapintensity;
5400 ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5401 ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5402 ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5403 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5404 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5405 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5406 if (VectorLength2(diffusecolor) > 0)
5408 // generate color arrays for the surfaces in this list
5409 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5411 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5412 int numverts = surface->num_vertices;
5413 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5414 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5415 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5416 // q3-style directional shading
5417 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5419 if ((f = DotProduct(c2, lightdir)) > 0)
5420 VectorMA(ambientcolor, f, diffusecolor, c);
5422 VectorCopy(ambientcolor, c);
5431 rsurface.lightmapcolor4f = rsurface.array_color4f;
5432 rsurface.lightmapcolor4f_bufferobject = 0;
5433 rsurface.lightmapcolor4f_bufferoffset = 0;
5437 r = ambientcolor[0];
5438 g = ambientcolor[1];
5439 b = ambientcolor[2];
5440 rsurface.lightmapcolor4f = NULL;
5441 rsurface.lightmapcolor4f_bufferobject = 0;
5442 rsurface.lightmapcolor4f_bufferoffset = 0;
5444 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5445 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5446 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5447 GL_Color(r, g, b, a);
5448 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5451 void RSurf_SetupDepthAndCulling(void)
5453 // submodels are biased to avoid z-fighting with world surfaces that they
5454 // may be exactly overlapping (avoids z-fighting artifacts on certain
5455 // doors and things in Quake maps)
5456 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5457 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5458 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5459 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5462 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5464 RSurf_SetupDepthAndCulling();
5465 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5467 rsurface.mode = RSURFMODE_SHOWSURFACES;
5469 GL_BlendFunc(GL_ONE, GL_ZERO);
5470 R_Mesh_ColorPointer(NULL, 0, 0);
5471 R_Mesh_ResetTextureState();
5473 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5474 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5477 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5479 // transparent sky would be ridiculous
5480 if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5482 if (rsurface.mode != RSURFMODE_SKY)
5484 if (rsurface.mode == RSURFMODE_GLSL)
5486 qglUseProgramObjectARB(0);CHECKGLERROR
5488 rsurface.mode = RSURFMODE_SKY;
5492 skyrendernow = false;
5494 // restore entity matrix
5495 R_Mesh_Matrix(&rsurface.matrix);
5497 RSurf_SetupDepthAndCulling();
5499 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5500 // skymasking on them, and Quake3 never did sky masking (unlike
5501 // software Quake and software Quake2), so disable the sky masking
5502 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5503 // and skymasking also looks very bad when noclipping outside the
5504 // level, so don't use it then either.
5505 if (r_refdef.worldmodel && r_refdef.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_viewcache.world_novis)
5507 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5508 R_Mesh_ColorPointer(NULL, 0, 0);
5509 R_Mesh_ResetTextureState();
5510 if (skyrendermasked)
5512 // depth-only (masking)
5513 GL_ColorMask(0,0,0,0);
5514 // just to make sure that braindead drivers don't draw
5515 // anything despite that colormask...
5516 GL_BlendFunc(GL_ZERO, GL_ONE);
5521 GL_BlendFunc(GL_ONE, GL_ZERO);
5523 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5524 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5525 if (skyrendermasked)
5526 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5530 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5532 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5535 if (rsurface.mode != RSURFMODE_GLSL)
5537 rsurface.mode = RSURFMODE_GLSL;
5538 R_Mesh_ResetTextureState();
5539 GL_Color(1, 1, 1, 1);
5542 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5543 R_Mesh_TexBind(0, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5544 R_Mesh_TexBind(1, R_GetTexture(rsurface.texture->basetexture));
5545 R_Mesh_TexBind(2, R_GetTexture(rsurface.texture->glosstexture));
5546 R_Mesh_TexBind(4, R_GetTexture(r_texture_fogattenuation));
5547 R_Mesh_TexBind(5, R_GetTexture(rsurface.texture->currentskinframe->pants));
5548 R_Mesh_TexBind(6, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5549 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5551 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5552 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5553 R_Mesh_ColorPointer(NULL, 0, 0);
5555 else if (rsurface.uselightmaptexture)
5557 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5558 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5559 R_Mesh_ColorPointer(NULL, 0, 0);
5563 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5564 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5565 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5567 R_Mesh_TexBind(9, R_GetTexture(rsurface.texture->currentskinframe->glow));
5568 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5569 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5571 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5573 // render background
5574 GL_BlendFunc(GL_ONE, GL_ZERO);
5576 GL_AlphaTest(false);
5578 GL_Color(1, 1, 1, 1);
5579 R_Mesh_ColorPointer(NULL, 0, 0);
5581 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5582 if (r_glsl_permutation)
5584 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5585 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5586 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5587 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5588 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5589 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5590 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction ? 11 : -1, r_glsl_permutation->loc_Texture_Reflection ? 12 : -1);
5593 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5594 GL_DepthMask(false);
5595 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5596 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5598 R_Mesh_TexBind(7, R_GetTexture(r_texture_grey128));
5599 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5600 R_Mesh_ColorPointer(NULL, 0, 0);
5602 else if (rsurface.uselightmaptexture)
5604 R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
5605 R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
5606 R_Mesh_ColorPointer(NULL, 0, 0);
5610 R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
5611 R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
5612 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5614 R_Mesh_TexBind(11, R_GetTexture(r_texture_white)); // changed per surface
5615 R_Mesh_TexBind(12, R_GetTexture(r_texture_white)); // changed per surface
5618 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5619 if (!r_glsl_permutation)
5622 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5623 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5624 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5625 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5626 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5627 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5629 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5631 GL_BlendFunc(GL_ONE, GL_ZERO);
5633 GL_AlphaTest(false);
5636 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5638 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5639 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);
5641 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
5645 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5646 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);
5648 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5650 if (rsurface.texture->backgroundnumskinframes && !(rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED))
5655 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5657 // OpenGL 1.3 path - anything not completely ancient
5658 int texturesurfaceindex;
5659 qboolean applycolor;
5663 const texturelayer_t *layer;
5664 if (rsurface.mode != RSURFMODE_MULTIPASS)
5665 rsurface.mode = RSURFMODE_MULTIPASS;
5666 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5668 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5671 int layertexrgbscale;
5672 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5674 if (layerindex == 0)
5678 GL_AlphaTest(false);
5679 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5682 GL_DepthMask(layer->depthmask);
5683 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5684 if ((layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2) && (gl_combine.integer || layer->depthmask))
5686 layertexrgbscale = 4;
5687 VectorScale(layer->color, 0.25f, layercolor);
5689 else if ((layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1) && (gl_combine.integer || layer->depthmask))
5691 layertexrgbscale = 2;
5692 VectorScale(layer->color, 0.5f, layercolor);
5696 layertexrgbscale = 1;
5697 VectorScale(layer->color, 1.0f, layercolor);
5699 layercolor[3] = layer->color[3];
5700 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5701 R_Mesh_ColorPointer(NULL, 0, 0);
5702 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5703 switch (layer->type)
5705 case TEXTURELAYERTYPE_LITTEXTURE:
5706 memset(&m, 0, sizeof(m));
5707 m.tex[0] = R_GetTexture(r_texture_white);
5708 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5709 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5710 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5711 m.tex[1] = R_GetTexture(layer->texture);
5712 m.texmatrix[1] = layer->texmatrix;
5713 m.texrgbscale[1] = layertexrgbscale;
5714 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5715 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5716 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5717 R_Mesh_TextureState(&m);
5718 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5719 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5720 else if (rsurface.uselightmaptexture)
5721 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5723 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5725 case TEXTURELAYERTYPE_TEXTURE:
5726 memset(&m, 0, sizeof(m));
5727 m.tex[0] = R_GetTexture(layer->texture);
5728 m.texmatrix[0] = layer->texmatrix;
5729 m.texrgbscale[0] = layertexrgbscale;
5730 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5731 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5732 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5733 R_Mesh_TextureState(&m);
5734 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5736 case TEXTURELAYERTYPE_FOG:
5737 memset(&m, 0, sizeof(m));
5738 m.texrgbscale[0] = layertexrgbscale;
5741 m.tex[0] = R_GetTexture(layer->texture);
5742 m.texmatrix[0] = layer->texmatrix;
5743 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5744 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5745 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5747 R_Mesh_TextureState(&m);
5748 // generate a color array for the fog pass
5749 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5750 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5754 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5755 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)
5757 f = 1 - FogPoint_Model(v);
5758 c[0] = layercolor[0];
5759 c[1] = layercolor[1];
5760 c[2] = layercolor[2];
5761 c[3] = f * layercolor[3];
5764 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5767 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5769 GL_LockArrays(0, 0);
5772 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5774 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5775 GL_AlphaTest(false);
5779 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5781 // OpenGL 1.1 - crusty old voodoo path
5782 int texturesurfaceindex;
5786 const texturelayer_t *layer;
5787 if (rsurface.mode != RSURFMODE_MULTIPASS)
5788 rsurface.mode = RSURFMODE_MULTIPASS;
5789 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5791 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5793 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5795 if (layerindex == 0)
5799 GL_AlphaTest(false);
5800 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5803 GL_DepthMask(layer->depthmask);
5804 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5805 R_Mesh_ColorPointer(NULL, 0, 0);
5806 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5807 switch (layer->type)
5809 case TEXTURELAYERTYPE_LITTEXTURE:
5810 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5812 // two-pass lit texture with 2x rgbscale
5813 // first the lightmap pass
5814 memset(&m, 0, sizeof(m));
5815 m.tex[0] = R_GetTexture(r_texture_white);
5816 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5817 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5818 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5819 R_Mesh_TextureState(&m);
5820 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5821 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5822 else if (rsurface.uselightmaptexture)
5823 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5825 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5826 GL_LockArrays(0, 0);
5827 // then apply the texture to it
5828 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5829 memset(&m, 0, sizeof(m));
5830 m.tex[0] = R_GetTexture(layer->texture);
5831 m.texmatrix[0] = layer->texmatrix;
5832 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5833 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5834 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5835 R_Mesh_TextureState(&m);
5836 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);
5840 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
5841 memset(&m, 0, sizeof(m));
5842 m.tex[0] = R_GetTexture(layer->texture);
5843 m.texmatrix[0] = layer->texmatrix;
5844 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5845 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5846 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5847 R_Mesh_TextureState(&m);
5848 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5849 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);
5851 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);
5854 case TEXTURELAYERTYPE_TEXTURE:
5855 // singletexture unlit texture with transparency support
5856 memset(&m, 0, sizeof(m));
5857 m.tex[0] = R_GetTexture(layer->texture);
5858 m.texmatrix[0] = layer->texmatrix;
5859 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5860 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5861 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5862 R_Mesh_TextureState(&m);
5863 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);
5865 case TEXTURELAYERTYPE_FOG:
5866 // singletexture fogging
5867 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5870 memset(&m, 0, sizeof(m));
5871 m.tex[0] = R_GetTexture(layer->texture);
5872 m.texmatrix[0] = layer->texmatrix;
5873 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5874 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5875 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5876 R_Mesh_TextureState(&m);
5879 R_Mesh_ResetTextureState();
5880 // generate a color array for the fog pass
5881 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5885 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5886 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)
5888 f = 1 - FogPoint_Model(v);
5889 c[0] = layer->color[0];
5890 c[1] = layer->color[1];
5891 c[2] = layer->color[2];
5892 c[3] = f * layer->color[3];
5895 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5898 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5900 GL_LockArrays(0, 0);
5903 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5905 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5906 GL_AlphaTest(false);
5910 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
5912 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
5914 rsurface.rtlight = NULL;
5918 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
5920 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
5922 if (rsurface.mode != RSURFMODE_MULTIPASS)
5923 rsurface.mode = RSURFMODE_MULTIPASS;
5924 if (r_depthfirst.integer == 3)
5926 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
5927 if (!r_view.showdebug)
5928 GL_Color(0, 0, 0, 1);
5930 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
5934 GL_ColorMask(0,0,0,0);
5937 RSurf_SetupDepthAndCulling();
5939 GL_BlendFunc(GL_ONE, GL_ZERO);
5941 GL_AlphaTest(false);
5942 R_Mesh_ColorPointer(NULL, 0, 0);
5943 R_Mesh_ResetTextureState();
5944 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5945 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5946 GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
5948 else if (r_depthfirst.integer == 3)
5950 else if (!r_view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
5952 GL_Color(0, 0, 0, 1);
5953 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5955 else if (r_showsurfaces.integer)
5957 if (rsurface.mode != RSURFMODE_MULTIPASS)
5958 rsurface.mode = RSURFMODE_MULTIPASS;
5959 RSurf_SetupDepthAndCulling();
5961 GL_BlendFunc(GL_ONE, GL_ZERO);
5962 GL_DepthMask(writedepth);
5964 GL_AlphaTest(false);
5965 R_Mesh_ColorPointer(NULL, 0, 0);
5966 R_Mesh_ResetTextureState();
5967 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5968 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5970 else if (gl_lightmaps.integer)
5973 if (rsurface.mode != RSURFMODE_MULTIPASS)
5974 rsurface.mode = RSURFMODE_MULTIPASS;
5975 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5977 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_view.cullface_back);
5978 GL_BlendFunc(GL_ONE, GL_ZERO);
5979 GL_DepthMask(writedepth);
5981 GL_AlphaTest(false);
5982 R_Mesh_ColorPointer(NULL, 0, 0);
5983 memset(&m, 0, sizeof(m));
5984 m.tex[0] = R_GetTexture(r_texture_white);
5985 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5986 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5987 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5988 R_Mesh_TextureState(&m);
5989 RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist);
5990 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5991 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5992 else if (rsurface.uselightmaptexture)
5993 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5995 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
5997 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
5998 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
5999 else if (rsurface.texture->currentnumlayers)
6001 // write depth for anything we skipped on the depth-only pass earlier
6002 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6004 RSurf_SetupDepthAndCulling();
6005 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6006 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6007 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6008 if (r_glsl.integer && gl_support_fragment_shader)
6009 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
6010 else if (gl_combine.integer && r_textureunits.integer >= 2)
6011 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
6013 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
6016 GL_LockArrays(0, 0);
6019 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6022 int texturenumsurfaces, endsurface;
6024 msurface_t *surface;
6025 msurface_t *texturesurfacelist[1024];
6027 // if the model is static it doesn't matter what value we give for
6028 // wantnormals and wanttangents, so this logic uses only rules applicable
6029 // to a model, knowing that they are meaningless otherwise
6030 if (ent == r_refdef.worldentity)
6031 RSurf_ActiveWorldEntity();
6032 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6033 RSurf_ActiveModelEntity(ent, false, false);
6035 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6037 for (i = 0;i < numsurfaces;i = j)
6040 surface = rsurface.modelsurfaces + surfacelist[i];
6041 texture = surface->texture;
6042 R_UpdateTextureInfo(ent, texture);
6043 rsurface.texture = texture->currentframe;
6044 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6045 // scan ahead until we find a different texture
6046 endsurface = min(i + 1024, numsurfaces);
6047 texturenumsurfaces = 0;
6048 texturesurfacelist[texturenumsurfaces++] = surface;
6049 for (;j < endsurface;j++)
6051 surface = rsurface.modelsurfaces + surfacelist[j];
6052 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6054 texturesurfacelist[texturenumsurfaces++] = surface;
6056 // render the range of surfaces
6057 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
6063 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6066 vec3_t tempcenter, center;
6068 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6071 for (i = 0;i < numsurfaces;i++)
6072 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6073 R_Water_AddWaterPlane(surfacelist[i]);
6076 // break the surface list down into batches by texture and use of lightmapping
6077 for (i = 0;i < numsurfaces;i = j)
6080 // texture is the base texture pointer, rsurface.texture is the
6081 // current frame/skin the texture is directing us to use (for example
6082 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6083 // use skin 1 instead)
6084 texture = surfacelist[i]->texture;
6085 rsurface.texture = texture->currentframe;
6086 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6087 if (!(rsurface.texture->currentmaterialflags & flagsmask))
6089 // if this texture is not the kind we want, skip ahead to the next one
6090 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6094 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6096 // transparent surfaces get pushed off into the transparent queue
6097 const msurface_t *surface = surfacelist[i];
6100 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6101 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6102 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6103 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6104 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
6108 // simply scan ahead until we find a different texture or lightmap state
6109 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6111 // render the range of surfaces
6112 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6117 float locboxvertex3f[6*4*3] =
6119 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6120 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6121 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6122 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6123 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6124 1,0,0, 0,0,0, 0,1,0, 1,1,0
6127 int locboxelement3i[6*2*3] =
6137 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6140 cl_locnode_t *loc = (cl_locnode_t *)ent;
6142 float vertex3f[6*4*3];
6144 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6145 GL_DepthMask(false);
6146 GL_DepthRange(0, 1);
6147 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6149 GL_CullFace(GL_NONE);
6150 R_Mesh_Matrix(&identitymatrix);
6152 R_Mesh_VertexPointer(vertex3f, 0, 0);
6153 R_Mesh_ColorPointer(NULL, 0, 0);
6154 R_Mesh_ResetTextureState();
6157 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_view.colorscale,
6158 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_view.colorscale,
6159 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_view.colorscale,
6160 surfacelist[0] < 0 ? 0.5f : 0.125f);
6162 if (VectorCompare(loc->mins, loc->maxs))
6164 VectorSet(size, 2, 2, 2);
6165 VectorMA(loc->mins, -0.5f, size, mins);
6169 VectorCopy(loc->mins, mins);
6170 VectorSubtract(loc->maxs, loc->mins, size);
6173 for (i = 0;i < 6*4*3;)
6174 for (j = 0;j < 3;j++, i++)
6175 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6177 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6180 void R_DrawLocs(void)
6183 cl_locnode_t *loc, *nearestloc;
6185 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6186 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6188 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6189 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6193 void R_DrawDebugModel(entity_render_t *ent)
6195 int i, j, k, l, flagsmask;
6196 const int *elements;
6198 msurface_t *surface;
6199 model_t *model = ent->model;
6202 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6204 R_Mesh_ColorPointer(NULL, 0, 0);
6205 R_Mesh_ResetTextureState();
6206 GL_DepthRange(0, 1);
6207 GL_DepthTest(!r_showdisabledepthtest.integer);
6208 GL_DepthMask(false);
6209 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6211 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6213 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6214 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6216 if (brush->colbrushf && brush->colbrushf->numtriangles)
6218 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6219 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, r_showcollisionbrushes.value);
6220 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6223 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6225 if (surface->num_collisiontriangles)
6227 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6228 GL_Color((i & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_view.colorscale, r_showcollisionbrushes.value);
6229 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6234 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6236 if (r_showtris.integer || r_shownormals.integer)
6238 if (r_showdisabledepthtest.integer)
6240 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6241 GL_DepthMask(false);
6245 GL_BlendFunc(GL_ONE, GL_ZERO);
6248 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6250 if (ent == r_refdef.worldentity && !r_viewcache.world_surfacevisible[j])
6252 rsurface.texture = surface->texture->currentframe;
6253 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6255 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6256 if (r_showtris.value > 0)
6258 if (!rsurface.texture->currentlayers->depthmask)
6259 GL_Color(r_view.colorscale, 0, 0, r_showtris.value);
6260 else if (ent == r_refdef.worldentity)
6261 GL_Color(r_view.colorscale, r_view.colorscale, r_view.colorscale, r_showtris.value);
6263 GL_Color(0, r_view.colorscale, 0, r_showtris.value);
6264 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6267 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6269 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6270 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6271 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6272 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6277 if (r_shownormals.value > 0)
6280 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6282 VectorCopy(rsurface.vertex3f + l * 3, v);
6283 GL_Color(r_view.colorscale, 0, 0, 1);
6284 qglVertex3f(v[0], v[1], v[2]);
6285 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6286 GL_Color(r_view.colorscale, 1, 1, 1);
6287 qglVertex3f(v[0], v[1], v[2]);
6292 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6294 VectorCopy(rsurface.vertex3f + l * 3, v);
6295 GL_Color(0, r_view.colorscale, 0, 1);
6296 qglVertex3f(v[0], v[1], v[2]);
6297 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6298 GL_Color(r_view.colorscale, 1, 1, 1);
6299 qglVertex3f(v[0], v[1], v[2]);
6304 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6306 VectorCopy(rsurface.vertex3f + l * 3, v);
6307 GL_Color(0, 0, r_view.colorscale, 1);
6308 qglVertex3f(v[0], v[1], v[2]);
6309 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6310 GL_Color(r_view.colorscale, 1, 1, 1);
6311 qglVertex3f(v[0], v[1], v[2]);
6318 rsurface.texture = NULL;
6322 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6323 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6325 int i, j, endj, f, flagsmask;
6326 msurface_t *surface;
6328 model_t *model = r_refdef.worldmodel;
6329 const int maxsurfacelist = 1024;
6330 int numsurfacelist = 0;
6331 msurface_t *surfacelist[1024];
6335 RSurf_ActiveWorldEntity();
6337 // update light styles on this submodel
6338 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6340 model_brush_lightstyleinfo_t *style;
6341 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6343 if (style->value != r_refdef.lightstylevalue[style->style])
6345 msurface_t *surfaces = model->data_surfaces;
6346 int *list = style->surfacelist;
6347 style->value = r_refdef.lightstylevalue[style->style];
6348 for (j = 0;j < style->numsurfaces;j++)
6349 surfaces[list[j]].cached_dlight = true;
6354 R_UpdateAllTextureInfo(r_refdef.worldentity);
6355 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6359 R_DrawDebugModel(r_refdef.worldentity);
6365 rsurface.uselightmaptexture = false;
6366 rsurface.texture = NULL;
6368 j = model->firstmodelsurface;
6369 endj = j + model->nummodelsurfaces;
6372 // quickly skip over non-visible surfaces
6373 for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
6375 // quickly iterate over visible surfaces
6376 for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
6378 // process this surface
6379 surface = model->data_surfaces + j;
6380 // if this surface fits the criteria, add it to the list
6381 if (surface->num_triangles)
6383 // if lightmap parameters changed, rebuild lightmap texture
6384 if (surface->cached_dlight)
6385 R_BuildLightMap(r_refdef.worldentity, surface);
6386 // add face to draw list
6387 surfacelist[numsurfacelist++] = surface;
6388 r_refdef.stats.world_triangles += surface->num_triangles;
6389 if (numsurfacelist >= maxsurfacelist)
6391 r_refdef.stats.world_surfaces += numsurfacelist;
6392 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6398 r_refdef.stats.world_surfaces += numsurfacelist;
6400 R_QueueSurfaceList(r_refdef.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6404 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6406 int i, j, f, flagsmask;
6407 msurface_t *surface, *endsurface;
6409 model_t *model = ent->model;
6410 const int maxsurfacelist = 1024;
6411 int numsurfacelist = 0;
6412 msurface_t *surfacelist[1024];
6416 // if the model is static it doesn't matter what value we give for
6417 // wantnormals and wanttangents, so this logic uses only rules applicable
6418 // to a model, knowing that they are meaningless otherwise
6419 if (ent == r_refdef.worldentity)
6420 RSurf_ActiveWorldEntity();
6421 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6422 RSurf_ActiveModelEntity(ent, false, false);
6424 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6426 // update light styles
6427 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6429 model_brush_lightstyleinfo_t *style;
6430 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6432 if (style->value != r_refdef.lightstylevalue[style->style])
6434 msurface_t *surfaces = model->data_surfaces;
6435 int *list = style->surfacelist;
6436 style->value = r_refdef.lightstylevalue[style->style];
6437 for (j = 0;j < style->numsurfaces;j++)
6438 surfaces[list[j]].cached_dlight = true;
6443 R_UpdateAllTextureInfo(ent);
6444 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6448 R_DrawDebugModel(ent);
6454 rsurface.uselightmaptexture = false;
6455 rsurface.texture = NULL;
6457 surface = model->data_surfaces + model->firstmodelsurface;
6458 endsurface = surface + model->nummodelsurfaces;
6459 for (;surface < endsurface;surface++)
6461 // if this surface fits the criteria, add it to the list
6462 if (surface->num_triangles)
6464 // if lightmap parameters changed, rebuild lightmap texture
6465 if (surface->cached_dlight)
6466 R_BuildLightMap(ent, surface);
6467 // add face to draw list
6468 surfacelist[numsurfacelist++] = surface;
6469 r_refdef.stats.entities_triangles += surface->num_triangles;
6470 if (numsurfacelist >= maxsurfacelist)
6472 r_refdef.stats.entities_surfaces += numsurfacelist;
6473 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6478 r_refdef.stats.entities_surfaces += numsurfacelist;
6480 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);