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;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
38 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
42 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
43 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
44 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
47 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
49 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "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"};
50 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
51 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
52 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
53 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)"};
54 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
55 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
56 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"};
57 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"};
58 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
59 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"};
60 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"};
61 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"};
62 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
63 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
64 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
65 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
66 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
67 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
68 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
69 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
70 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
71 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
72 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
73 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
74 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
75 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
76 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
77 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
78 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
79 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
80 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
81 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"};
82 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"};
83 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
84 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
86 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
87 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
88 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
89 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
90 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
91 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
92 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
93 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
95 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)"};
97 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
98 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)"};
99 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
100 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
101 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
102 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
103 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
104 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
105 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
106 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
107 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
109 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)"};
110 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
111 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"};
112 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
113 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
115 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
116 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
117 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
118 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
120 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
121 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
122 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
123 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
124 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
125 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
126 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
128 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
129 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
130 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
131 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)"};
133 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"};
135 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"};
137 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
139 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
140 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
141 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"};
142 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
143 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
144 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
145 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
147 extern cvar_t v_glslgamma;
149 extern qboolean v_flipped_state;
151 static struct r_bloomstate_s
156 int bloomwidth, bloomheight;
158 int screentexturewidth, screentextureheight;
159 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
161 int bloomtexturewidth, bloomtextureheight;
162 rtexture_t *texture_bloom;
164 // arrays for rendering the screen passes
165 float screentexcoord2f[8];
166 float bloomtexcoord2f[8];
167 float offsettexcoord2f[8];
169 r_viewport_t viewport;
173 r_waterstate_t r_waterstate;
175 /// shadow volume bsp struct with automatically growing nodes buffer
178 rtexture_t *r_texture_blanknormalmap;
179 rtexture_t *r_texture_white;
180 rtexture_t *r_texture_grey128;
181 rtexture_t *r_texture_black;
182 rtexture_t *r_texture_notexture;
183 rtexture_t *r_texture_whitecube;
184 rtexture_t *r_texture_normalizationcube;
185 rtexture_t *r_texture_fogattenuation;
186 rtexture_t *r_texture_gammaramps;
187 unsigned int r_texture_gammaramps_serial;
188 //rtexture_t *r_texture_fogintensity;
190 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
191 unsigned int r_numqueries;
192 unsigned int r_maxqueries;
194 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
195 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
197 /// vertex coordinates for a quad that covers the screen exactly
198 const float r_screenvertex3f[12] =
206 extern void R_DrawModelShadows(void);
208 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
211 for (i = 0;i < verts;i++)
222 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
225 for (i = 0;i < verts;i++)
235 // FIXME: move this to client?
238 if (gamemode == GAME_NEHAHRA)
240 Cvar_Set("gl_fogenable", "0");
241 Cvar_Set("gl_fogdensity", "0.2");
242 Cvar_Set("gl_fogred", "0.3");
243 Cvar_Set("gl_foggreen", "0.3");
244 Cvar_Set("gl_fogblue", "0.3");
246 r_refdef.fog_density = 0;
247 r_refdef.fog_red = 0;
248 r_refdef.fog_green = 0;
249 r_refdef.fog_blue = 0;
250 r_refdef.fog_alpha = 1;
251 r_refdef.fog_start = 0;
252 r_refdef.fog_end = 0;
255 float FogForDistance(vec_t dist)
257 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
258 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
261 float FogPoint_World(const vec3_t p)
263 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
266 float FogPoint_Model(const vec3_t p)
268 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
271 static void R_BuildBlankTextures(void)
273 unsigned char data[4];
274 data[2] = 128; // normal X
275 data[1] = 128; // normal Y
276 data[0] = 255; // normal Z
277 data[3] = 128; // height
278 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
283 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
288 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
293 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
296 static void R_BuildNoTexture(void)
299 unsigned char pix[16][16][4];
300 // this makes a light grey/dark grey checkerboard texture
301 for (y = 0;y < 16;y++)
303 for (x = 0;x < 16;x++)
305 if ((y < 8) ^ (x < 8))
321 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
324 static void R_BuildWhiteCube(void)
326 unsigned char data[6*1*1*4];
327 memset(data, 255, sizeof(data));
328 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
331 static void R_BuildNormalizationCube(void)
335 vec_t s, t, intensity;
337 unsigned char data[6][NORMSIZE][NORMSIZE][4];
338 for (side = 0;side < 6;side++)
340 for (y = 0;y < NORMSIZE;y++)
342 for (x = 0;x < NORMSIZE;x++)
344 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
345 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
380 intensity = 127.0f / sqrt(DotProduct(v, v));
381 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
382 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
383 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
384 data[side][y][x][3] = 255;
388 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
391 static void R_BuildFogTexture(void)
395 unsigned char data1[FOGWIDTH][4];
396 //unsigned char data2[FOGWIDTH][4];
399 r_refdef.fogmasktable_start = r_refdef.fog_start;
400 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
401 r_refdef.fogmasktable_range = r_refdef.fogrange;
402 r_refdef.fogmasktable_density = r_refdef.fog_density;
404 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
405 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
407 d = (x * r - r_refdef.fogmasktable_start);
408 if(developer.integer >= 100)
409 Con_Printf("%f ", d);
411 if (r_fog_exp2.integer)
412 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
414 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
415 if(developer.integer >= 100)
416 Con_Printf(" : %f ", alpha);
417 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
418 if(developer.integer >= 100)
419 Con_Printf(" = %f\n", alpha);
420 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
423 for (x = 0;x < FOGWIDTH;x++)
425 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
430 //data2[x][0] = 255 - b;
431 //data2[x][1] = 255 - b;
432 //data2[x][2] = 255 - b;
435 if (r_texture_fogattenuation)
437 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
438 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
442 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);
443 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
447 static const char *builtinshaderstring =
448 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
449 "// written by Forest 'LordHavoc' Hale\n"
451 "// enable various extensions depending on permutation:\n"
453 "#ifdef USESHADOWMAPRECT\n"
454 "# extension GL_ARB_texture_rectangle : enable\n"
457 "#ifdef USESHADOWMAP2D\n"
458 "# ifdef GL_EXT_gpu_shader4\n"
459 "# extension GL_EXT_gpu_shader4 : enable\n"
461 "# ifdef GL_ARB_texture_gather\n"
462 "# extension GL_ARB_texture_gather : enable\n"
463 "# define USETEXTUREGATHER\n"
465 "# ifdef GL_AMD_texture_texture4\n"
466 "# extension GL_AMD_texture_texture4 : enable\n"
467 "# define USETEXTUREGATHER\n"
468 "# define textureGather texture4\n"
473 "#ifdef USESHADOWMAPCUBE\n"
474 "# extension GL_EXT_gpu_shader4 : enable\n"
477 "#ifdef USESHADOWSAMPLER\n"
478 "# extension GL_ARB_shadow : enable\n"
481 "// common definitions between vertex shader and fragment shader:\n"
483 "//#ifdef __GLSL_CG_DATA_TYPES\n"
484 "//# define myhalf half\n"
485 "//# define myhalf2 half2\n"
486 "//# define myhalf3half3\n"
487 "//# define myhalf4 half4\n"
489 "# define myhalf float\n"
490 "# define myhalf2 vec2\n"
491 "# define myhalf3 vec3\n"
492 "# define myhalf4 vec4\n"
495 "#ifdef MODE_DEPTH_OR_SHADOW\n"
497 "# ifdef VERTEX_SHADER\n"
500 " gl_Position = ftransform();\n"
505 "#ifdef MODE_SHOWDEPTH\n"
506 "# ifdef VERTEX_SHADER\n"
509 " gl_Position = ftransform();\n"
510 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
513 "# ifdef FRAGMENT_SHADER\n"
516 " gl_FragColor = gl_Color;\n"
520 "#else // !MODE_SHOWDEPTH\n"
522 "#ifdef MODE_POSTPROCESS\n"
523 "# ifdef VERTEX_SHADER\n"
526 " gl_FrontColor = gl_Color;\n"
527 " gl_Position = ftransform();\n"
528 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
530 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
534 "# ifdef FRAGMENT_SHADER\n"
536 "uniform sampler2D Texture_First;\n"
538 "uniform sampler2D Texture_Second;\n"
540 "#ifdef USEGAMMARAMPS\n"
541 "uniform sampler2D Texture_GammaRamps;\n"
543 "#ifdef USESATURATION\n"
544 "uniform float Saturation;\n"
546 "#ifdef USEVIEWTINT\n"
547 "uniform vec4 TintColor;\n"
549 "//uncomment these if you want to use them:\n"
550 "uniform vec4 UserVec1;\n"
551 "// uniform vec4 UserVec2;\n"
552 "// uniform vec4 UserVec3;\n"
553 "// uniform vec4 UserVec4;\n"
554 "// uniform float ClientTime;\n"
555 "uniform vec2 PixelSize;\n"
558 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
560 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
562 "#ifdef USEVIEWTINT\n"
563 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
566 "#ifdef USEPOSTPROCESSING\n"
567 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
568 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
569 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
570 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
571 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
572 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
573 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
574 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
577 "#ifdef USESATURATION\n"
578 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
579 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
580 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
581 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
584 "#ifdef USEGAMMARAMPS\n"
585 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
586 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
587 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
594 "#ifdef MODE_GENERIC\n"
595 "# ifdef VERTEX_SHADER\n"
598 " gl_FrontColor = gl_Color;\n"
599 "# ifdef USEDIFFUSE\n"
600 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
602 "# ifdef USESPECULAR\n"
603 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
605 " gl_Position = ftransform();\n"
608 "# ifdef FRAGMENT_SHADER\n"
610 "# ifdef USEDIFFUSE\n"
611 "uniform sampler2D Texture_First;\n"
613 "# ifdef USESPECULAR\n"
614 "uniform sampler2D Texture_Second;\n"
619 " gl_FragColor = gl_Color;\n"
620 "# ifdef USEDIFFUSE\n"
621 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
624 "# ifdef USESPECULAR\n"
625 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
627 "# ifdef USECOLORMAPPING\n"
628 " gl_FragColor *= tex2;\n"
631 " gl_FragColor += tex2;\n"
633 "# ifdef USEVERTEXTEXTUREBLEND\n"
634 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
639 "#else // !MODE_GENERIC\n"
641 "varying vec2 TexCoord;\n"
642 "#ifdef USEVERTEXTEXTUREBLEND\n"
643 "varying vec2 TexCoord2;\n"
645 "varying vec2 TexCoordLightmap;\n"
647 "#ifdef MODE_LIGHTSOURCE\n"
648 "varying vec3 CubeVector;\n"
651 "#ifdef MODE_LIGHTSOURCE\n"
652 "varying vec3 LightVector;\n"
654 "#ifdef MODE_LIGHTDIRECTION\n"
655 "varying vec3 LightVector;\n"
658 "varying vec3 EyeVector;\n"
660 "varying vec3 EyeVectorModelSpace;\n"
663 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
664 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
665 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
667 "#ifdef MODE_WATER\n"
668 "varying vec4 ModelViewProjectionPosition;\n"
670 "#ifdef MODE_REFRACTION\n"
671 "varying vec4 ModelViewProjectionPosition;\n"
673 "#ifdef USEREFLECTION\n"
674 "varying vec4 ModelViewProjectionPosition;\n"
681 "// vertex shader specific:\n"
682 "#ifdef VERTEX_SHADER\n"
684 "uniform vec3 LightPosition;\n"
685 "uniform vec3 EyePosition;\n"
686 "uniform vec3 LightDir;\n"
688 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
692 " gl_FrontColor = gl_Color;\n"
693 " // copy the surface texcoord\n"
694 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
695 "#ifdef USEVERTEXTEXTUREBLEND\n"
696 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
698 "#ifndef MODE_LIGHTSOURCE\n"
699 "# ifndef MODE_LIGHTDIRECTION\n"
700 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
704 "#ifdef MODE_LIGHTSOURCE\n"
705 " // transform vertex position into light attenuation/cubemap space\n"
706 " // (-1 to +1 across the light box)\n"
707 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
709 " // transform unnormalized light direction into tangent space\n"
710 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
711 " // normalize it per pixel)\n"
712 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
713 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
714 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
715 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
718 "#ifdef MODE_LIGHTDIRECTION\n"
719 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
720 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
721 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
724 " // transform unnormalized eye direction into tangent space\n"
726 " vec3 EyeVectorModelSpace;\n"
728 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
729 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
730 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
731 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
733 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
734 " VectorS = gl_MultiTexCoord1.xyz;\n"
735 " VectorT = gl_MultiTexCoord2.xyz;\n"
736 " VectorR = gl_MultiTexCoord3.xyz;\n"
739 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
740 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
741 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
742 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
745 "// transform vertex to camera space, using ftransform to match non-VS\n"
747 " gl_Position = ftransform();\n"
749 "#ifdef MODE_WATER\n"
750 " ModelViewProjectionPosition = gl_Position;\n"
752 "#ifdef MODE_REFRACTION\n"
753 " ModelViewProjectionPosition = gl_Position;\n"
755 "#ifdef USEREFLECTION\n"
756 " ModelViewProjectionPosition = gl_Position;\n"
760 "#endif // VERTEX_SHADER\n"
765 "// fragment shader specific:\n"
766 "#ifdef FRAGMENT_SHADER\n"
768 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
769 "uniform sampler2D Texture_Normal;\n"
770 "uniform sampler2D Texture_Color;\n"
771 "uniform sampler2D Texture_Gloss;\n"
772 "uniform sampler2D Texture_Glow;\n"
773 "uniform sampler2D Texture_SecondaryNormal;\n"
774 "uniform sampler2D Texture_SecondaryColor;\n"
775 "uniform sampler2D Texture_SecondaryGloss;\n"
776 "uniform sampler2D Texture_SecondaryGlow;\n"
777 "uniform sampler2D Texture_Pants;\n"
778 "uniform sampler2D Texture_Shirt;\n"
779 "uniform sampler2D Texture_FogMask;\n"
780 "uniform sampler2D Texture_Lightmap;\n"
781 "uniform sampler2D Texture_Deluxemap;\n"
782 "uniform sampler2D Texture_Refraction;\n"
783 "uniform sampler2D Texture_Reflection;\n"
784 "uniform sampler2D Texture_Attenuation;\n"
785 "uniform samplerCube Texture_Cube;\n"
787 "#define showshadowmap 0\n"
789 "#ifdef USESHADOWMAPRECT\n"
790 "# ifdef USESHADOWSAMPLER\n"
791 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
793 "uniform sampler2DRect Texture_ShadowMapRect;\n"
797 "#ifdef USESHADOWMAP2D\n"
798 "# ifdef USESHADOWSAMPLER\n"
799 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
801 "uniform sampler2D Texture_ShadowMap2D;\n"
805 "#ifdef USESHADOWMAPVSDCT\n"
806 "uniform samplerCube Texture_CubeProjection;\n"
809 "#ifdef USESHADOWMAPCUBE\n"
810 "# ifdef USESHADOWSAMPLER\n"
811 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
813 "uniform samplerCube Texture_ShadowMapCube;\n"
817 "uniform myhalf3 LightColor;\n"
818 "uniform myhalf3 AmbientColor;\n"
819 "uniform myhalf3 DiffuseColor;\n"
820 "uniform myhalf3 SpecularColor;\n"
821 "uniform myhalf3 Color_Pants;\n"
822 "uniform myhalf3 Color_Shirt;\n"
823 "uniform myhalf3 FogColor;\n"
825 "uniform myhalf4 TintColor;\n"
828 "//#ifdef MODE_WATER\n"
829 "uniform vec4 DistortScaleRefractReflect;\n"
830 "uniform vec4 ScreenScaleRefractReflect;\n"
831 "uniform vec4 ScreenCenterRefractReflect;\n"
832 "uniform myhalf4 RefractColor;\n"
833 "uniform myhalf4 ReflectColor;\n"
834 "uniform myhalf ReflectFactor;\n"
835 "uniform myhalf ReflectOffset;\n"
837 "//# ifdef MODE_REFRACTION\n"
838 "//uniform vec4 DistortScaleRefractReflect;\n"
839 "//uniform vec4 ScreenScaleRefractReflect;\n"
840 "//uniform vec4 ScreenCenterRefractReflect;\n"
841 "//uniform myhalf4 RefractColor;\n"
842 "//# ifdef USEREFLECTION\n"
843 "//uniform myhalf4 ReflectColor;\n"
846 "//# ifdef USEREFLECTION\n"
847 "//uniform vec4 DistortScaleRefractReflect;\n"
848 "//uniform vec4 ScreenScaleRefractReflect;\n"
849 "//uniform vec4 ScreenCenterRefractReflect;\n"
850 "//uniform myhalf4 ReflectColor;\n"
855 "uniform myhalf GlowScale;\n"
856 "uniform myhalf SceneBrightness;\n"
858 "uniform float OffsetMapping_Scale;\n"
859 "uniform float OffsetMapping_Bias;\n"
860 "uniform float FogRangeRecip;\n"
862 "uniform myhalf AmbientScale;\n"
863 "uniform myhalf DiffuseScale;\n"
864 "uniform myhalf SpecularScale;\n"
865 "uniform myhalf SpecularPower;\n"
867 "#ifdef USEOFFSETMAPPING\n"
868 "vec2 OffsetMapping(vec2 TexCoord)\n"
870 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
871 " // 14 sample relief mapping: linear search and then binary search\n"
872 " // this basically steps forward a small amount repeatedly until it finds\n"
873 " // itself inside solid, then jitters forward and back using decreasing\n"
874 " // amounts to find the impact\n"
875 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
876 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
877 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
878 " vec3 RT = vec3(TexCoord, 1);\n"
879 " OffsetVector *= 0.1;\n"
880 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
881 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
882 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
883 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
884 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
885 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
886 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
887 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
888 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
889 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
890 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
891 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
892 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
893 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
896 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
897 " // this basically moves forward the full distance, and then backs up based\n"
898 " // on height of samples\n"
899 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
900 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
901 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
902 " TexCoord += OffsetVector;\n"
903 " OffsetVector *= 0.333;\n"
904 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
905 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
906 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
907 " return TexCoord;\n"
910 "#endif // USEOFFSETMAPPING\n"
912 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
913 "uniform vec4 ShadowMap_TextureScale;\n"
914 "uniform vec4 ShadowMap_Parameters;\n"
917 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
918 "vec3 GetShadowMapTC2D(vec3 dir)\n"
920 " vec3 adir = abs(dir);\n"
921 "# ifndef USESHADOWMAPVSDCT\n"
925 " if (adir.x > adir.y)\n"
927 " if (adir.x > adir.z)\n"
930 " if (dir.x >= 0.0) { tc = vec2(-dir.z, -dir.y); offset = vec2(0.5, 0.5); } // +X\n"
931 " else { tc = vec2( dir.z, -dir.y); offset = vec2(1.5, 0.5); } // -X\n"
936 " if (dir.z >= 0.0) { tc = vec2( dir.x, -dir.y); offset = vec2(0.5, 2.5); } // +Z\n"
937 " else { tc = vec2(-dir.x, -dir.y); offset = vec2(1.5, 2.5); } // -Z\n"
942 " if (adir.y > adir.z)\n"
945 " if (dir.y >= 0.0) { tc = vec2( dir.x, dir.z); offset = vec2(0.5, 1.5); } // +Y\n"
946 " else { tc = vec2( dir.x, -dir.z); offset = vec2(1.5, 1.5); } // -Y\n"
951 " if (dir.z >= 0.0) { tc = vec2( dir.x, -dir.y); offset = vec2(0.5, 2.5); } // +Z\n"
952 " else { tc = vec2(-dir.x, -dir.y); offset = vec2(1.5, 2.5); } // -Z\n"
956 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma + vec3(offset * ShadowMap_Parameters.y, ShadowMap_Parameters.z);\n"
957 " stc.xy *= ShadowMap_TextureScale.xy;\n"
960 " return vec3(textureCube(Texture_CubeProjection, dir.xyz).ra * ShadowMap_Parameters.xy, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
963 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
965 "#ifdef USESHADOWMAPCUBE\n"
966 "vec4 GetShadowMapTCCube(vec3 dir)\n"
968 " vec3 adir = abs(dir);\n"
969 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
973 "#if !showshadowmap\n"
974 "# ifdef USESHADOWMAPRECT\n"
975 "float ShadowMapCompare(vec3 dir)\n"
977 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
979 "# ifdef USESHADOWSAMPLER\n"
981 "# ifdef USESHADOWMAPPCF\n"
982 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
983 " f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
985 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
990 "# ifdef USESHADOWMAPPCF\n"
991 "# if USESHADOWMAPPCF > 1\n"
992 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
993 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
994 " vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0))),\n"
995 " row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0))),\n"
996 " row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0))),\n"
997 " row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0))),\n"
998 " cols = row2 + row3 + mix(row1, row4, offset.y);\n"
999 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1001 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1002 " vec2 offset = fract(shadowmaptc.xy);\n"
1003 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0))),\n"
1004 " row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0))),\n"
1005 " row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0))),\n"
1006 " cols = row2 + mix(row1, row3, offset.y);\n"
1007 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1010 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1018 "# ifdef USESHADOWMAP2D\n"
1019 "float ShadowMapCompare(vec3 dir)\n"
1021 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1024 "# ifdef USESHADOWSAMPLER\n"
1025 "# ifdef USESHADOWMAPPCF\n"
1026 "# ifdef GL_EXT_gpu_shader4\n"
1027 "# define texval(x, y) shadow2DOffset(Texture_ShadowMap2D, shadowmaptc, ivec2(x, y)).r\n"
1029 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy + vec2(x, y)*ShadowMap_TextureScale.xy, shadowmaptc.z)).r \n"
1031 " f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1033 " f = shadow2D(Texture_ShadowMap2D, shadowmaptc).r;\n"
1036 "# ifdef USESHADOWMAPPCF\n"
1037 "# ifdef USETEXTUREGATHER\n"
1038 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale.zw - 0.5, offset = fract(center);\n"
1039 " vec4 group1 = step(shadowmaptc.z, textureGather(Texture_ShadowMap2D, (center + vec2(-1.0, -1.0))*ShadowMap_TextureScale.xy)),\n"
1040 " group2 = step(shadowmaptc.z, textureGather(Texture_ShadowMap2D, (center + vec2( 1.0, -1.0))*ShadowMap_TextureScale.xy)),\n"
1041 " group3 = step(shadowmaptc.z, textureGather(Texture_ShadowMap2D, (center + vec2(-1.0, 1.0))*ShadowMap_TextureScale.xy)),\n"
1042 " group4 = step(shadowmaptc.z, textureGather(Texture_ShadowMap2D, (center + vec2( 1.0, 1.0))*ShadowMap_TextureScale.xy)),\n"
1043 " cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1044 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1045 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1047 "# if USESHADOWMAPPCF > 1\n"
1048 "# ifdef GL_EXT_gpu_shader4\n"
1049 " vec2 center = shadowmaptc.xy - 0.5*ShadowMap_TextureScale.xy, offset = fract(center*ShadowMap_TextureScale.zw);\n"
1050 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1052 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale.zw - 0.5, offset = fract(center);\n"
1053 "# define texval(x, y) texture2D(Texture_ShadowMap2D, (center + vec2(x, y))*ShadowMap_TextureScale.xy).r \n"
1055 " vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0))),\n"
1056 " row2 = step(shadowmaptc.z, vec4(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0), texval( 2.0, 0.0))),\n"
1057 " row3 = step(shadowmaptc.z, vec4(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0), texval( 2.0, 1.0))),\n"
1058 " row4 = step(shadowmaptc.z, vec4(texval(-1.0, 2.0), texval( 0.0, 2.0), texval( 1.0, 2.0), texval( 2.0, 2.0))),\n"
1059 " cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1060 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1062 "# ifdef GL_EXT_gpu_shader4\n"
1063 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, shadowmaptc.xy, ivec2(x, y)).r\n"
1065 "# define texval(x, y) texture2D(Texture_ShadowMap2D, shadowmaptc.xy + vec2(x, y)*ShadowMap_TextureScale.xy).r \n"
1067 " vec2 offset = fract(shadowmaptc.xy*ShadowMap_TextureScale.zw);\n"
1068 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0))),\n"
1069 " row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0))),\n"
1070 " row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0))),\n"
1071 " cols = row2 + mix(row1, row3, offset.y);\n"
1072 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1076 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy).r);\n"
1083 "# ifdef USESHADOWMAPCUBE\n"
1084 "float ShadowMapCompare(vec3 dir)\n"
1086 " // apply depth texture cubemap as light filter\n"
1087 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1089 "# ifdef USESHADOWSAMPLER\n"
1090 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1092 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1099 "#ifdef MODE_WATER\n"
1104 "#ifdef USEOFFSETMAPPING\n"
1105 " // apply offsetmapping\n"
1106 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1107 "#define TexCoord TexCoordOffset\n"
1110 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1111 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1112 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1113 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1114 " // FIXME temporary hack to detect the case that the reflection\n"
1115 " // gets blackened at edges due to leaving the area that contains actual\n"
1117 " // Remove this 'ack once we have a better way to stop this thing from\n"
1119 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1120 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1121 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1122 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1123 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1124 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1125 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1126 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1127 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1128 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1129 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1130 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1133 "#else // !MODE_WATER\n"
1134 "#ifdef MODE_REFRACTION\n"
1136 "// refraction pass\n"
1139 "#ifdef USEOFFSETMAPPING\n"
1140 " // apply offsetmapping\n"
1141 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1142 "#define TexCoord TexCoordOffset\n"
1145 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1146 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1147 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1148 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1149 " // FIXME temporary hack to detect the case that the reflection\n"
1150 " // gets blackened at edges due to leaving the area that contains actual\n"
1152 " // Remove this 'ack once we have a better way to stop this thing from\n"
1154 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1155 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1156 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1157 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1158 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1159 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1162 "#else // !MODE_REFRACTION\n"
1165 "#ifdef USEOFFSETMAPPING\n"
1166 " // apply offsetmapping\n"
1167 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1168 "#define TexCoord TexCoordOffset\n"
1171 " // combine the diffuse textures (base, pants, shirt)\n"
1172 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1173 "#ifdef USECOLORMAPPING\n"
1174 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1176 "#ifdef USEVERTEXTEXTUREBLEND\n"
1177 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1178 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1179 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1180 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1182 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1185 "#ifdef USEDIFFUSE\n"
1186 " // get the surface normal and the gloss color\n"
1187 "# ifdef USEVERTEXTEXTUREBLEND\n"
1188 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1189 "# ifdef USESPECULAR\n"
1190 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1193 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1194 "# ifdef USESPECULAR\n"
1195 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1202 "#ifdef MODE_LIGHTSOURCE\n"
1203 " // light source\n"
1205 " // calculate surface normal, light normal, and specular normal\n"
1206 " // compute color intensity for the two textures (colormap and glossmap)\n"
1207 " // scale by light color and attenuation as efficiently as possible\n"
1208 " // (do as much scalar math as possible rather than vector math)\n"
1209 "# ifdef USEDIFFUSE\n"
1210 " // get the light normal\n"
1211 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1213 "# ifdef USESPECULAR\n"
1214 "# ifndef USEEXACTSPECULARMATH\n"
1215 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1218 " // calculate directional shading\n"
1219 "# ifdef USEEXACTSPECULARMATH\n"
1220 " color.rgb = 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(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower)) * glosscolor);\n"
1222 " color.rgb = 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)) * glosscolor);\n"
1225 "# ifdef USEDIFFUSE\n"
1226 " // calculate directional shading\n"
1227 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1229 " // calculate directionless shading\n"
1230 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1234 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1235 "#if !showshadowmap\n"
1236 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1240 "# ifdef USECUBEFILTER\n"
1241 " // apply light cubemap filter\n"
1242 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1243 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1245 "#endif // MODE_LIGHTSOURCE\n"
1250 "#ifdef MODE_LIGHTDIRECTION\n"
1251 " // directional model lighting\n"
1252 "# ifdef USEDIFFUSE\n"
1253 " // get the light normal\n"
1254 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1256 "# ifdef USESPECULAR\n"
1257 " // calculate directional shading\n"
1258 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1259 "# ifdef USEEXACTSPECULARMATH\n"
1260 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1262 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1263 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1266 "# ifdef USEDIFFUSE\n"
1268 " // calculate directional shading\n"
1269 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1271 " color.rgb *= AmbientColor;\n"
1274 "#endif // MODE_LIGHTDIRECTION\n"
1279 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1280 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1282 " // get the light normal\n"
1283 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1284 " myhalf3 diffusenormal;\n"
1285 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1286 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1287 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1288 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1289 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1290 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1291 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1292 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1293 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1294 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1295 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1296 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1297 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1298 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1299 "# ifdef USESPECULAR\n"
1300 "# ifdef USEEXACTSPECULARMATH\n"
1301 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1303 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1304 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1308 " // apply lightmap color\n"
1309 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1310 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1315 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1316 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1318 " // get the light normal\n"
1319 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1320 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1321 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1322 "# ifdef USESPECULAR\n"
1323 "# ifdef USEEXACTSPECULARMATH\n"
1324 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1326 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1327 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1331 " // apply lightmap color\n"
1332 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1333 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1338 "#ifdef MODE_LIGHTMAP\n"
1339 " // apply lightmap color\n"
1340 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1341 "#endif // MODE_LIGHTMAP\n"
1346 "#ifdef MODE_VERTEXCOLOR\n"
1347 " // apply lightmap color\n"
1348 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1349 "#endif // MODE_VERTEXCOLOR\n"
1354 "#ifdef MODE_FLATCOLOR\n"
1355 "#endif // MODE_FLATCOLOR\n"
1363 " color *= TintColor;\n"
1366 "#ifdef USEVERTEXTEXTUREBLEND\n"
1367 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1369 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1373 " color.rgb *= SceneBrightness;\n"
1375 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1377 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1380 " // 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"
1381 "#ifdef USEREFLECTION\n"
1382 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1383 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1384 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1385 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1386 " // FIXME temporary hack to detect the case that the reflection\n"
1387 " // gets blackened at edges due to leaving the area that contains actual\n"
1389 " // Remove this 'ack once we have a better way to stop this thing from\n"
1391 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1392 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1393 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1394 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1395 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1396 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1399 " gl_FragColor = vec4(color);\n"
1401 "#if showshadowmap\n"
1402 "# ifdef USESHADOWMAPRECT\n"
1403 "# ifdef USESHADOWSAMPLER\n"
1404 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1406 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1409 "# ifdef USESHADOWMAP2D\n"
1410 "# ifdef USESHADOWSAMPLER\n"
1411 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1413 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1417 "# ifdef USESHADOWMAPCUBE\n"
1418 "# ifdef USESHADOWSAMPLER\n"
1419 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1421 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1426 "#endif // !MODE_REFRACTION\n"
1427 "#endif // !MODE_WATER\n"
1429 "#endif // FRAGMENT_SHADER\n"
1431 "#endif // !MODE_GENERIC\n"
1432 "#endif // !MODE_POSTPROCESS\n"
1433 "#endif // !MODE_SHOWDEPTH\n"
1434 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1437 typedef struct shaderpermutationinfo_s
1439 const char *pretext;
1442 shaderpermutationinfo_t;
1444 typedef struct shadermodeinfo_s
1446 const char *vertexfilename;
1447 const char *geometryfilename;
1448 const char *fragmentfilename;
1449 const char *pretext;
1454 typedef enum shaderpermutation_e
1456 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1457 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1458 SHADERPERMUTATION_VIEWTINT = 1<<1, ///< view tint (postprocessing only)
1459 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1460 SHADERPERMUTATION_SATURATION = 1<<2, ///< saturation (postprocessing only)
1461 SHADERPERMUTATION_FOG = 1<<3, ///< tint the color by fog color or black if using additive blend mode
1462 SHADERPERMUTATION_GAMMARAMPS = 1<<3, ///< gamma (postprocessing only)
1463 SHADERPERMUTATION_CUBEFILTER = 1<<4, ///< (lightsource) use cubemap light filter
1464 SHADERPERMUTATION_GLOW = 1<<5, ///< (lightmap) blend in an additive glow texture
1465 SHADERPERMUTATION_BLOOM = 1<<5, ///< bloom (postprocessing only)
1466 SHADERPERMUTATION_SPECULAR = 1<<6, ///< (lightsource or deluxemapping) render specular effects
1467 SHADERPERMUTATION_POSTPROCESSING = 1<<6, ///< user defined postprocessing (postprocessing only)
1468 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<7, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1469 SHADERPERMUTATION_REFLECTION = 1<<8, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1470 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, ///< adjust texcoords to roughly simulate a displacement mapped surface
1471 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1472 SHADERPERMUTATION_SHADOWMAPRECT = 1<<11, ///< (lightsource) use shadowmap rectangle texture as light filter
1473 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<12, ///< (lightsource) use shadowmap cubemap texture as light filter
1474 SHADERPERMUTATION_SHADOWMAP2D = 1<<13, ///< (lightsource) use shadowmap rectangle texture as light filter
1475 SHADERPERMUTATION_SHADOWMAPPCF = 1<<14, //< (lightsource) use percentage closer filtering on shadowmap test results
1476 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<15, //< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1477 SHADERPERMUTATION_SHADOWSAMPLER = 1<<16, //< (lightsource) use hardware shadowmap test
1478 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<17, //< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1479 SHADERPERMUTATION_LIMIT = 1<<18, ///< size of permutations array
1480 SHADERPERMUTATION_COUNT = 18 ///< size of shaderpermutationinfo array
1482 shaderpermutation_t;
1484 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1485 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1487 {"#define USEDIFFUSE\n", " diffuse"},
1488 {"#define USEVERTEXTEXTUREBLEND\n#define USEVIEWTINT\n", " vertextextureblend/tint"},
1489 {"#define USECOLORMAPPING\n#define USESATURATION\n", " colormapping/saturation"},
1490 {"#define USEFOG\n#define USEGAMMARAMPS\n", " fog/gammaramps"},
1491 {"#define USECUBEFILTER\n", " cubefilter"},
1492 {"#define USEGLOW\n#define USEBLOOM\n", " glow/bloom"},
1493 {"#define USESPECULAR\n#define USEPOSTPROCESSING", " specular/postprocessing"},
1494 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1495 {"#define USEREFLECTION\n", " reflection"},
1496 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1497 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1498 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1499 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1500 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1501 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1502 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1503 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1504 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1507 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1508 typedef enum shadermode_e
1510 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1511 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1512 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1513 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1514 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1515 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1516 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1517 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1518 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1519 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1520 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1521 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1522 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1527 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1528 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1530 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1531 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1532 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1533 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1534 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1535 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1536 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1537 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1538 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1539 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1540 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1541 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1542 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1545 struct r_glsl_permutation_s;
1546 typedef struct r_glsl_permutation_s
1548 /// hash lookup data
1549 struct r_glsl_permutation_s *hashnext;
1551 unsigned int permutation;
1553 /// indicates if we have tried compiling this permutation already
1555 /// 0 if compilation failed
1557 /// locations of detected uniforms in program object, or -1 if not found
1558 int loc_Texture_First;
1559 int loc_Texture_Second;
1560 int loc_Texture_GammaRamps;
1561 int loc_Texture_Normal;
1562 int loc_Texture_Color;
1563 int loc_Texture_Gloss;
1564 int loc_Texture_Glow;
1565 int loc_Texture_SecondaryNormal;
1566 int loc_Texture_SecondaryColor;
1567 int loc_Texture_SecondaryGloss;
1568 int loc_Texture_SecondaryGlow;
1569 int loc_Texture_Pants;
1570 int loc_Texture_Shirt;
1571 int loc_Texture_FogMask;
1572 int loc_Texture_Lightmap;
1573 int loc_Texture_Deluxemap;
1574 int loc_Texture_Attenuation;
1575 int loc_Texture_Cube;
1576 int loc_Texture_Refraction;
1577 int loc_Texture_Reflection;
1578 int loc_Texture_ShadowMapRect;
1579 int loc_Texture_ShadowMapCube;
1580 int loc_Texture_ShadowMap2D;
1581 int loc_Texture_CubeProjection;
1583 int loc_LightPosition;
1584 int loc_EyePosition;
1585 int loc_Color_Pants;
1586 int loc_Color_Shirt;
1587 int loc_FogRangeRecip;
1588 int loc_AmbientScale;
1589 int loc_DiffuseScale;
1590 int loc_SpecularScale;
1591 int loc_SpecularPower;
1593 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1594 int loc_OffsetMapping_Scale;
1596 int loc_AmbientColor;
1597 int loc_DiffuseColor;
1598 int loc_SpecularColor;
1600 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1601 int loc_GammaCoeff; ///< 1 / gamma
1602 int loc_DistortScaleRefractReflect;
1603 int loc_ScreenScaleRefractReflect;
1604 int loc_ScreenCenterRefractReflect;
1605 int loc_RefractColor;
1606 int loc_ReflectColor;
1607 int loc_ReflectFactor;
1608 int loc_ReflectOffset;
1616 int loc_ShadowMap_TextureScale;
1617 int loc_ShadowMap_Parameters;
1619 r_glsl_permutation_t;
1621 #define SHADERPERMUTATION_HASHSIZE 4096
1623 /// information about each possible shader permutation
1624 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1625 /// currently selected permutation
1626 r_glsl_permutation_t *r_glsl_permutation;
1627 /// storage for permutations linked in the hash table
1628 memexpandablearray_t r_glsl_permutationarray;
1630 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1632 //unsigned int hashdepth = 0;
1633 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1634 r_glsl_permutation_t *p;
1635 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1637 if (p->mode == mode && p->permutation == permutation)
1639 //if (hashdepth > 10)
1640 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1645 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1647 p->permutation = permutation;
1648 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1649 r_glsl_permutationhash[mode][hashindex] = p;
1650 //if (hashdepth > 10)
1651 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1655 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1658 if (!filename || !filename[0])
1660 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1663 if (printfromdisknotice)
1664 Con_DPrint("from disk... ");
1665 return shaderstring;
1667 else if (!strcmp(filename, "glsl/default.glsl"))
1669 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1670 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1672 return shaderstring;
1675 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1678 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1679 int vertstrings_count = 0;
1680 int geomstrings_count = 0;
1681 int fragstrings_count = 0;
1682 char *vertexstring, *geometrystring, *fragmentstring;
1683 const char *vertstrings_list[32+3];
1684 const char *geomstrings_list[32+3];
1685 const char *fragstrings_list[32+3];
1686 char permutationname[256];
1693 permutationname[0] = 0;
1694 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1695 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1696 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1698 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1700 // the first pretext is which type of shader to compile as
1701 // (later these will all be bound together as a program object)
1702 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1703 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1704 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1706 // the second pretext is the mode (for example a light source)
1707 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1708 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1709 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1710 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1712 // now add all the permutation pretexts
1713 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1715 if (permutation & (1<<i))
1717 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1718 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1719 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1720 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1724 // keep line numbers correct
1725 vertstrings_list[vertstrings_count++] = "\n";
1726 geomstrings_list[geomstrings_count++] = "\n";
1727 fragstrings_list[fragstrings_count++] = "\n";
1731 // now append the shader text itself
1732 vertstrings_list[vertstrings_count++] = vertexstring;
1733 geomstrings_list[geomstrings_count++] = geometrystring;
1734 fragstrings_list[fragstrings_count++] = fragmentstring;
1736 // if any sources were NULL, clear the respective list
1738 vertstrings_count = 0;
1739 if (!geometrystring)
1740 geomstrings_count = 0;
1741 if (!fragmentstring)
1742 fragstrings_count = 0;
1744 // compile the shader program
1745 if (vertstrings_count + geomstrings_count + fragstrings_count)
1746 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1750 qglUseProgramObjectARB(p->program);CHECKGLERROR
1751 // look up all the uniform variable names we care about, so we don't
1752 // have to look them up every time we set them
1753 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1754 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1755 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1756 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1757 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1758 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1759 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1760 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1761 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1762 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1763 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1764 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1765 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1766 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1767 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1768 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1769 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1770 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1771 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1772 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1773 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1774 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1775 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1776 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1777 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1778 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1779 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1780 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1781 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1782 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1783 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1784 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1785 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1786 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1787 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1788 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1789 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1790 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1791 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1792 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1793 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1794 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1795 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1796 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1797 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1798 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1799 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1800 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1801 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1802 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1803 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1804 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1805 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1806 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1807 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1808 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1809 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1810 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1811 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1812 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1813 // initialize the samplers to refer to the texture units we use
1814 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1815 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1816 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1817 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1818 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1819 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1820 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1821 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1822 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1823 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1824 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1825 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1826 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1827 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1828 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1829 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1830 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1831 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1832 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1833 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1834 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1835 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1836 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1837 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1839 if (developer.integer)
1840 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1843 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1847 Mem_Free(vertexstring);
1849 Mem_Free(geometrystring);
1851 Mem_Free(fragmentstring);
1854 void R_GLSL_Restart_f(void)
1856 unsigned int i, limit;
1857 r_glsl_permutation_t *p;
1858 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1859 for (i = 0;i < limit;i++)
1861 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1863 GL_Backend_FreeProgram(p->program);
1864 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1867 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1870 void R_GLSL_DumpShader_f(void)
1874 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1877 Con_Printf("failed to write to glsl/default.glsl\n");
1881 FS_Print(file, "/* The engine may define the following macros:\n");
1882 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1883 for (i = 0;i < SHADERMODE_COUNT;i++)
1884 FS_Print(file, shadermodeinfo[i].pretext);
1885 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1886 FS_Print(file, shaderpermutationinfo[i].pretext);
1887 FS_Print(file, "*/\n");
1888 FS_Print(file, builtinshaderstring);
1891 Con_Printf("glsl/default.glsl written\n");
1894 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1896 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1897 if (r_glsl_permutation != perm)
1899 r_glsl_permutation = perm;
1900 if (!r_glsl_permutation->program)
1902 if (!r_glsl_permutation->compiled)
1903 R_GLSL_CompilePermutation(perm, mode, permutation);
1904 if (!r_glsl_permutation->program)
1906 // remove features until we find a valid permutation
1908 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1910 // reduce i more quickly whenever it would not remove any bits
1911 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1912 if (!(permutation & j))
1915 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1916 if (!r_glsl_permutation->compiled)
1917 R_GLSL_CompilePermutation(perm, mode, permutation);
1918 if (r_glsl_permutation->program)
1921 if (i >= SHADERPERMUTATION_COUNT)
1923 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");
1924 Cvar_SetValueQuick(&r_glsl, 0);
1925 R_GLSL_Restart_f(); // unload shaders
1926 return; // no bit left to clear
1931 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1935 void R_SetupGenericShader(qboolean usetexture)
1937 if (gl_support_fragment_shader)
1939 if (r_glsl.integer && r_glsl_usegeneric.integer)
1940 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1941 else if (r_glsl_permutation)
1943 r_glsl_permutation = NULL;
1944 qglUseProgramObjectARB(0);CHECKGLERROR
1949 void R_SetupGenericTwoTextureShader(int texturemode)
1951 if (gl_support_fragment_shader)
1953 if (r_glsl.integer && r_glsl_usegeneric.integer)
1954 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1955 else if (r_glsl_permutation)
1957 r_glsl_permutation = NULL;
1958 qglUseProgramObjectARB(0);CHECKGLERROR
1961 if (!r_glsl_permutation)
1963 if (texturemode == GL_DECAL && gl_combine.integer)
1964 texturemode = GL_INTERPOLATE_ARB;
1965 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1969 void R_SetupDepthOrShadowShader(void)
1971 if (gl_support_fragment_shader)
1973 if (r_glsl.integer && r_glsl_usegeneric.integer)
1974 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1975 else if (r_glsl_permutation)
1977 r_glsl_permutation = NULL;
1978 qglUseProgramObjectARB(0);CHECKGLERROR
1983 void R_SetupShowDepthShader(void)
1985 if (gl_support_fragment_shader)
1987 if (r_glsl.integer && r_glsl_usegeneric.integer)
1988 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
1989 else if (r_glsl_permutation)
1991 r_glsl_permutation = NULL;
1992 qglUseProgramObjectARB(0);CHECKGLERROR
1997 extern rtexture_t *r_shadow_attenuationgradienttexture;
1998 extern rtexture_t *r_shadow_attenuation2dtexture;
1999 extern rtexture_t *r_shadow_attenuation3dtexture;
2000 extern qboolean r_shadow_usingshadowmaprect;
2001 extern qboolean r_shadow_usingshadowmapcube;
2002 extern qboolean r_shadow_usingshadowmap2d;
2003 extern float r_shadow_shadowmap_texturescale[4];
2004 extern float r_shadow_shadowmap_parameters[4];
2005 extern qboolean r_shadow_shadowmapvsdct;
2006 extern qboolean r_shadow_shadowmapsampler;
2007 extern int r_shadow_shadowmappcf;
2008 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2010 // select a permutation of the lighting shader appropriate to this
2011 // combination of texture, entity, light source, and fogging, only use the
2012 // minimum features necessary to avoid wasting rendering time in the
2013 // fragment shader on features that are not being used
2014 unsigned int permutation = 0;
2015 unsigned int mode = 0;
2016 // TODO: implement geometry-shader based shadow volumes someday
2017 if (r_glsl_offsetmapping.integer)
2019 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2020 if (r_glsl_offsetmapping_reliefmapping.integer)
2021 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2023 if (rsurfacepass == RSURFPASS_BACKGROUND)
2025 // distorted background
2026 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2027 mode = SHADERMODE_WATER;
2029 mode = SHADERMODE_REFRACTION;
2031 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2034 mode = SHADERMODE_LIGHTSOURCE;
2035 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2036 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2037 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2038 permutation |= SHADERPERMUTATION_CUBEFILTER;
2039 if (diffusescale > 0)
2040 permutation |= SHADERPERMUTATION_DIFFUSE;
2041 if (specularscale > 0)
2042 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2043 if (r_refdef.fogenabled)
2044 permutation |= SHADERPERMUTATION_FOG;
2045 if (rsurface.texture->colormapping)
2046 permutation |= SHADERPERMUTATION_COLORMAPPING;
2047 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2049 if (r_shadow_usingshadowmaprect)
2050 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2051 if (r_shadow_usingshadowmap2d)
2052 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2053 if (r_shadow_usingshadowmapcube)
2054 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2055 else if(r_shadow_shadowmapvsdct)
2056 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2058 if (r_shadow_shadowmapsampler)
2059 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2060 if (r_shadow_shadowmappcf > 1)
2061 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2062 else if (r_shadow_shadowmappcf)
2063 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2066 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2068 // unshaded geometry (fullbright or ambient model lighting)
2069 mode = SHADERMODE_FLATCOLOR;
2070 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2071 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2072 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2073 permutation |= SHADERPERMUTATION_GLOW;
2074 if (r_refdef.fogenabled)
2075 permutation |= SHADERPERMUTATION_FOG;
2076 if (rsurface.texture->colormapping)
2077 permutation |= SHADERPERMUTATION_COLORMAPPING;
2078 if (r_glsl_offsetmapping.integer)
2080 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2081 if (r_glsl_offsetmapping_reliefmapping.integer)
2082 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2084 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2085 permutation |= SHADERPERMUTATION_REFLECTION;
2087 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2089 // directional model lighting
2090 mode = SHADERMODE_LIGHTDIRECTION;
2091 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2092 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2093 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2094 permutation |= SHADERPERMUTATION_GLOW;
2095 permutation |= SHADERPERMUTATION_DIFFUSE;
2096 if (specularscale > 0)
2097 permutation |= SHADERPERMUTATION_SPECULAR;
2098 if (r_refdef.fogenabled)
2099 permutation |= SHADERPERMUTATION_FOG;
2100 if (rsurface.texture->colormapping)
2101 permutation |= SHADERPERMUTATION_COLORMAPPING;
2102 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2103 permutation |= SHADERPERMUTATION_REFLECTION;
2105 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2107 // ambient model lighting
2108 mode = SHADERMODE_LIGHTDIRECTION;
2109 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2110 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2111 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2112 permutation |= SHADERPERMUTATION_GLOW;
2113 if (r_refdef.fogenabled)
2114 permutation |= SHADERPERMUTATION_FOG;
2115 if (rsurface.texture->colormapping)
2116 permutation |= SHADERPERMUTATION_COLORMAPPING;
2117 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2118 permutation |= SHADERPERMUTATION_REFLECTION;
2123 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2125 // deluxemapping (light direction texture)
2126 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2127 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2129 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2130 permutation |= SHADERPERMUTATION_DIFFUSE;
2131 if (specularscale > 0)
2132 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2134 else if (r_glsl_deluxemapping.integer >= 2)
2136 // fake deluxemapping (uniform light direction in tangentspace)
2137 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2138 permutation |= SHADERPERMUTATION_DIFFUSE;
2139 if (specularscale > 0)
2140 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2142 else if (rsurface.uselightmaptexture)
2144 // ordinary lightmapping (q1bsp, q3bsp)
2145 mode = SHADERMODE_LIGHTMAP;
2149 // ordinary vertex coloring (q3bsp)
2150 mode = SHADERMODE_VERTEXCOLOR;
2152 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2153 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2154 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2155 permutation |= SHADERPERMUTATION_GLOW;
2156 if (r_refdef.fogenabled)
2157 permutation |= SHADERPERMUTATION_FOG;
2158 if (rsurface.texture->colormapping)
2159 permutation |= SHADERPERMUTATION_COLORMAPPING;
2160 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2161 permutation |= SHADERPERMUTATION_REFLECTION;
2163 if(permutation & SHADERPERMUTATION_SPECULAR)
2164 if(r_shadow_glossexact.integer)
2165 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2166 R_SetupShader_SetPermutation(mode, permutation);
2167 if (mode == SHADERMODE_LIGHTSOURCE)
2169 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2170 if (permutation & SHADERPERMUTATION_DIFFUSE)
2172 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2173 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2174 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2175 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2179 // ambient only is simpler
2180 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale, rsurface.texture->lightmapcolor[3]);
2181 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2182 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2183 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2185 // additive passes are only darkened by fog, not tinted
2186 if (r_glsl_permutation->loc_FogColor >= 0)
2187 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2188 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1], r_shadow_shadowmap_texturescale[2], r_shadow_shadowmap_texturescale[3]);
2189 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2193 if (mode == SHADERMODE_LIGHTDIRECTION)
2195 if (r_glsl_permutation->loc_AmbientColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale * 0.5f, rsurface.modellight_ambient[1] * ambientscale * 0.5f, rsurface.modellight_ambient[2] * ambientscale * 0.5f);
2196 if (r_glsl_permutation->loc_DiffuseColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale * 0.5f, rsurface.modellight_diffuse[1] * diffusescale * 0.5f, rsurface.modellight_diffuse[2] * diffusescale * 0.5f);
2197 if (r_glsl_permutation->loc_SpecularColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * 0.5f, rsurface.modellight_diffuse[1] * specularscale * 0.5f, rsurface.modellight_diffuse[2] * specularscale * 0.5f);
2198 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2202 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2203 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2204 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2206 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]);
2207 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
2208 // additive passes are only darkened by fog, not tinted
2209 if (r_glsl_permutation->loc_FogColor >= 0)
2211 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2212 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2214 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2216 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);
2217 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]);
2218 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]);
2219 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2220 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2221 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2222 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2224 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2225 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
2226 if (r_glsl_permutation->loc_Color_Pants >= 0)
2228 if (rsurface.texture->currentskinframe->pants)
2229 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2231 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2233 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2235 if (rsurface.texture->currentskinframe->shirt)
2236 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2238 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2240 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
2241 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2243 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2247 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2249 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2253 #define SKINFRAME_HASH 1024
2257 int loadsequence; // incremented each level change
2258 memexpandablearray_t array;
2259 skinframe_t *hash[SKINFRAME_HASH];
2262 r_skinframe_t r_skinframe;
2264 void R_SkinFrame_PrepareForPurge(void)
2266 r_skinframe.loadsequence++;
2267 // wrap it without hitting zero
2268 if (r_skinframe.loadsequence >= 200)
2269 r_skinframe.loadsequence = 1;
2272 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2276 // mark the skinframe as used for the purging code
2277 skinframe->loadsequence = r_skinframe.loadsequence;
2280 void R_SkinFrame_Purge(void)
2284 for (i = 0;i < SKINFRAME_HASH;i++)
2286 for (s = r_skinframe.hash[i];s;s = s->next)
2288 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2290 if (s->merged == s->base)
2292 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2293 R_PurgeTexture(s->stain );s->stain = NULL;
2294 R_PurgeTexture(s->merged);s->merged = NULL;
2295 R_PurgeTexture(s->base );s->base = NULL;
2296 R_PurgeTexture(s->pants );s->pants = NULL;
2297 R_PurgeTexture(s->shirt );s->shirt = NULL;
2298 R_PurgeTexture(s->nmap );s->nmap = NULL;
2299 R_PurgeTexture(s->gloss );s->gloss = NULL;
2300 R_PurgeTexture(s->glow );s->glow = NULL;
2301 R_PurgeTexture(s->fog );s->fog = NULL;
2302 s->loadsequence = 0;
2308 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2310 char basename[MAX_QPATH];
2312 Image_StripImageExtension(name, basename, sizeof(basename));
2314 if( last == NULL ) {
2316 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2317 item = r_skinframe.hash[hashindex];
2322 // linearly search through the hash bucket
2323 for( ; item ; item = item->next ) {
2324 if( !strcmp( item->basename, basename ) ) {
2331 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2335 char basename[MAX_QPATH];
2337 Image_StripImageExtension(name, basename, sizeof(basename));
2339 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2340 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2341 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2345 rtexture_t *dyntexture;
2346 // check whether its a dynamic texture
2347 dyntexture = CL_GetDynTexture( basename );
2348 if (!add && !dyntexture)
2350 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2351 memset(item, 0, sizeof(*item));
2352 strlcpy(item->basename, basename, sizeof(item->basename));
2353 item->base = dyntexture; // either NULL or dyntexture handle
2354 item->textureflags = textureflags;
2355 item->comparewidth = comparewidth;
2356 item->compareheight = compareheight;
2357 item->comparecrc = comparecrc;
2358 item->next = r_skinframe.hash[hashindex];
2359 r_skinframe.hash[hashindex] = item;
2361 else if( item->base == NULL )
2363 rtexture_t *dyntexture;
2364 // check whether its a dynamic texture
2365 // 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]
2366 dyntexture = CL_GetDynTexture( basename );
2367 item->base = dyntexture; // either NULL or dyntexture handle
2370 R_SkinFrame_MarkUsed(item);
2374 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2376 unsigned long long avgcolor[5], wsum; \
2384 for(pix = 0; pix < cnt; ++pix) \
2387 for(comp = 0; comp < 3; ++comp) \
2389 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2392 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2394 for(comp = 0; comp < 3; ++comp) \
2395 avgcolor[comp] += getpixel * w; \
2398 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2399 avgcolor[4] += getpixel; \
2401 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2403 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2404 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2405 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2406 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2409 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2411 // FIXME: it should be possible to disable loading various layers using
2412 // cvars, to prevent wasted loading time and memory usage if the user does
2414 qboolean loadnormalmap = true;
2415 qboolean loadgloss = true;
2416 qboolean loadpantsandshirt = true;
2417 qboolean loadglow = true;
2419 unsigned char *pixels;
2420 unsigned char *bumppixels;
2421 unsigned char *basepixels = NULL;
2422 int basepixels_width;
2423 int basepixels_height;
2424 skinframe_t *skinframe;
2428 if (cls.state == ca_dedicated)
2431 // return an existing skinframe if already loaded
2432 // if loading of the first image fails, don't make a new skinframe as it
2433 // would cause all future lookups of this to be missing
2434 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2435 if (skinframe && skinframe->base)
2438 basepixels = loadimagepixelsbgra(name, complain, true);
2439 if (basepixels == NULL)
2442 if (developer_loading.integer)
2443 Con_Printf("loading skin \"%s\"\n", name);
2445 // we've got some pixels to store, so really allocate this new texture now
2447 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2448 skinframe->stain = NULL;
2449 skinframe->merged = NULL;
2450 skinframe->base = r_texture_notexture;
2451 skinframe->pants = NULL;
2452 skinframe->shirt = NULL;
2453 skinframe->nmap = r_texture_blanknormalmap;
2454 skinframe->gloss = NULL;
2455 skinframe->glow = NULL;
2456 skinframe->fog = NULL;
2458 basepixels_width = image_width;
2459 basepixels_height = image_height;
2460 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);
2462 if (textureflags & TEXF_ALPHA)
2464 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2465 if (basepixels[j] < 255)
2467 if (j < basepixels_width * basepixels_height * 4)
2469 // has transparent pixels
2471 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2472 for (j = 0;j < image_width * image_height * 4;j += 4)
2477 pixels[j+3] = basepixels[j+3];
2479 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);
2484 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2485 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2487 // _norm is the name used by tenebrae and has been adopted as standard
2490 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2492 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2496 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2498 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2499 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2500 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2502 Mem_Free(bumppixels);
2504 else if (r_shadow_bumpscale_basetexture.value > 0)
2506 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2507 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2508 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
2512 // _luma is supported for tenebrae compatibility
2513 // (I think it's a very stupid name, but oh well)
2514 // _glow is the preferred name
2515 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;}
2516 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;}
2517 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;}
2518 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;}
2521 Mem_Free(basepixels);
2526 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2529 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2532 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)
2537 for (i = 0;i < width*height;i++)
2538 if (((unsigned char *)&palette[in[i]])[3] > 0)
2540 if (i == width*height)
2543 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2546 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2547 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2550 unsigned char *temp1, *temp2;
2551 skinframe_t *skinframe;
2553 if (cls.state == ca_dedicated)
2556 // if already loaded just return it, otherwise make a new skinframe
2557 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2558 if (skinframe && skinframe->base)
2561 skinframe->stain = NULL;
2562 skinframe->merged = NULL;
2563 skinframe->base = r_texture_notexture;
2564 skinframe->pants = NULL;
2565 skinframe->shirt = NULL;
2566 skinframe->nmap = r_texture_blanknormalmap;
2567 skinframe->gloss = NULL;
2568 skinframe->glow = NULL;
2569 skinframe->fog = NULL;
2571 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2575 if (developer_loading.integer)
2576 Con_Printf("loading 32bit skin \"%s\"\n", name);
2578 if (r_shadow_bumpscale_basetexture.value > 0)
2580 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2581 temp2 = temp1 + width * height * 4;
2582 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2583 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2586 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2587 if (textureflags & TEXF_ALPHA)
2589 for (i = 3;i < width * height * 4;i += 4)
2590 if (skindata[i] < 255)
2592 if (i < width * height * 4)
2594 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2595 memcpy(fogpixels, skindata, width * height * 4);
2596 for (i = 0;i < width * height * 4;i += 4)
2597 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2598 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2599 Mem_Free(fogpixels);
2603 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2604 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2609 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2612 unsigned char *temp1, *temp2;
2613 unsigned int *palette;
2614 skinframe_t *skinframe;
2616 if (cls.state == ca_dedicated)
2619 // if already loaded just return it, otherwise make a new skinframe
2620 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2621 if (skinframe && skinframe->base)
2624 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2626 skinframe->stain = NULL;
2627 skinframe->merged = NULL;
2628 skinframe->base = r_texture_notexture;
2629 skinframe->pants = NULL;
2630 skinframe->shirt = NULL;
2631 skinframe->nmap = r_texture_blanknormalmap;
2632 skinframe->gloss = NULL;
2633 skinframe->glow = NULL;
2634 skinframe->fog = NULL;
2636 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2640 if (developer_loading.integer)
2641 Con_Printf("loading quake skin \"%s\"\n", name);
2643 if (r_shadow_bumpscale_basetexture.value > 0)
2645 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2646 temp2 = temp1 + width * height * 4;
2647 // use either a custom palette or the quake palette
2648 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2649 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2650 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2653 // use either a custom palette, or the quake palette
2654 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2655 if (loadglowtexture)
2656 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2657 if (loadpantsandshirt)
2659 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2660 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2662 if (skinframe->pants || skinframe->shirt)
2663 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
2664 if (textureflags & TEXF_ALPHA)
2666 for (i = 0;i < width * height;i++)
2667 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2669 if (i < width * height)
2670 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2673 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2674 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
2679 skinframe_t *R_SkinFrame_LoadMissing(void)
2681 skinframe_t *skinframe;
2683 if (cls.state == ca_dedicated)
2686 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2687 skinframe->stain = NULL;
2688 skinframe->merged = NULL;
2689 skinframe->base = r_texture_notexture;
2690 skinframe->pants = NULL;
2691 skinframe->shirt = NULL;
2692 skinframe->nmap = r_texture_blanknormalmap;
2693 skinframe->gloss = NULL;
2694 skinframe->glow = NULL;
2695 skinframe->fog = NULL;
2697 skinframe->avgcolor[0] = rand() / RAND_MAX;
2698 skinframe->avgcolor[1] = rand() / RAND_MAX;
2699 skinframe->avgcolor[2] = rand() / RAND_MAX;
2700 skinframe->avgcolor[3] = 1;
2705 void gl_main_start(void)
2709 memset(r_queries, 0, sizeof(r_queries));
2711 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2712 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2714 // set up r_skinframe loading system for textures
2715 memset(&r_skinframe, 0, sizeof(r_skinframe));
2716 r_skinframe.loadsequence = 1;
2717 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2719 r_main_texturepool = R_AllocTexturePool();
2720 R_BuildBlankTextures();
2722 if (gl_texturecubemap)
2725 R_BuildNormalizationCube();
2727 r_texture_fogattenuation = NULL;
2728 r_texture_gammaramps = NULL;
2729 //r_texture_fogintensity = NULL;
2730 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2731 memset(&r_waterstate, 0, sizeof(r_waterstate));
2732 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2733 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2734 memset(&r_svbsp, 0, sizeof (r_svbsp));
2736 r_refdef.fogmasktable_density = 0;
2739 extern rtexture_t *loadingscreentexture;
2740 void gl_main_shutdown(void)
2743 qglDeleteQueriesARB(r_maxqueries, r_queries);
2747 memset(r_queries, 0, sizeof(r_queries));
2749 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2750 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2752 // clear out the r_skinframe state
2753 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2754 memset(&r_skinframe, 0, sizeof(r_skinframe));
2757 Mem_Free(r_svbsp.nodes);
2758 memset(&r_svbsp, 0, sizeof (r_svbsp));
2759 R_FreeTexturePool(&r_main_texturepool);
2760 loadingscreentexture = NULL;
2761 r_texture_blanknormalmap = NULL;
2762 r_texture_white = NULL;
2763 r_texture_grey128 = NULL;
2764 r_texture_black = NULL;
2765 r_texture_whitecube = NULL;
2766 r_texture_normalizationcube = NULL;
2767 r_texture_fogattenuation = NULL;
2768 r_texture_gammaramps = NULL;
2769 //r_texture_fogintensity = NULL;
2770 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2771 memset(&r_waterstate, 0, sizeof(r_waterstate));
2775 extern void CL_ParseEntityLump(char *entitystring);
2776 void gl_main_newmap(void)
2778 // FIXME: move this code to client
2780 char *entities, entname[MAX_QPATH];
2783 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2784 l = (int)strlen(entname) - 4;
2785 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2787 memcpy(entname + l, ".ent", 5);
2788 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2790 CL_ParseEntityLump(entities);
2795 if (cl.worldmodel->brush.entities)
2796 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2800 void GL_Main_Init(void)
2802 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2804 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2805 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2806 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2807 if (gamemode == GAME_NEHAHRA)
2809 Cvar_RegisterVariable (&gl_fogenable);
2810 Cvar_RegisterVariable (&gl_fogdensity);
2811 Cvar_RegisterVariable (&gl_fogred);
2812 Cvar_RegisterVariable (&gl_foggreen);
2813 Cvar_RegisterVariable (&gl_fogblue);
2814 Cvar_RegisterVariable (&gl_fogstart);
2815 Cvar_RegisterVariable (&gl_fogend);
2816 Cvar_RegisterVariable (&gl_skyclip);
2818 Cvar_RegisterVariable(&r_motionblur);
2819 Cvar_RegisterVariable(&r_motionblur_maxblur);
2820 Cvar_RegisterVariable(&r_motionblur_bmin);
2821 Cvar_RegisterVariable(&r_motionblur_vmin);
2822 Cvar_RegisterVariable(&r_motionblur_vmax);
2823 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2824 Cvar_RegisterVariable(&r_motionblur_randomize);
2825 Cvar_RegisterVariable(&r_damageblur);
2826 Cvar_RegisterVariable(&r_animcache);
2827 Cvar_RegisterVariable(&r_depthfirst);
2828 Cvar_RegisterVariable(&r_useinfinitefarclip);
2829 Cvar_RegisterVariable(&r_nearclip);
2830 Cvar_RegisterVariable(&r_showbboxes);
2831 Cvar_RegisterVariable(&r_showsurfaces);
2832 Cvar_RegisterVariable(&r_showtris);
2833 Cvar_RegisterVariable(&r_shownormals);
2834 Cvar_RegisterVariable(&r_showlighting);
2835 Cvar_RegisterVariable(&r_showshadowvolumes);
2836 Cvar_RegisterVariable(&r_showcollisionbrushes);
2837 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2838 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2839 Cvar_RegisterVariable(&r_showdisabledepthtest);
2840 Cvar_RegisterVariable(&r_drawportals);
2841 Cvar_RegisterVariable(&r_drawentities);
2842 Cvar_RegisterVariable(&r_cullentities_trace);
2843 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2844 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2845 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2846 Cvar_RegisterVariable(&r_drawviewmodel);
2847 Cvar_RegisterVariable(&r_speeds);
2848 Cvar_RegisterVariable(&r_fullbrights);
2849 Cvar_RegisterVariable(&r_wateralpha);
2850 Cvar_RegisterVariable(&r_dynamic);
2851 Cvar_RegisterVariable(&r_fullbright);
2852 Cvar_RegisterVariable(&r_shadows);
2853 Cvar_RegisterVariable(&r_shadows_darken);
2854 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
2855 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
2856 Cvar_RegisterVariable(&r_shadows_throwdistance);
2857 Cvar_RegisterVariable(&r_shadows_throwdirection);
2858 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2859 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2860 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2861 Cvar_RegisterVariable(&r_fog_exp2);
2862 Cvar_RegisterVariable(&r_drawfog);
2863 Cvar_RegisterVariable(&r_textureunits);
2864 Cvar_RegisterVariable(&r_glsl);
2865 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2866 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2867 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2868 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2869 Cvar_RegisterVariable(&r_glsl_postprocess);
2870 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2871 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2872 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2873 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2874 Cvar_RegisterVariable(&r_glsl_usegeneric);
2875 Cvar_RegisterVariable(&r_water);
2876 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2877 Cvar_RegisterVariable(&r_water_clippingplanebias);
2878 Cvar_RegisterVariable(&r_water_refractdistort);
2879 Cvar_RegisterVariable(&r_water_reflectdistort);
2880 Cvar_RegisterVariable(&r_lerpsprites);
2881 Cvar_RegisterVariable(&r_lerpmodels);
2882 Cvar_RegisterVariable(&r_lerplightstyles);
2883 Cvar_RegisterVariable(&r_waterscroll);
2884 Cvar_RegisterVariable(&r_bloom);
2885 Cvar_RegisterVariable(&r_bloom_colorscale);
2886 Cvar_RegisterVariable(&r_bloom_brighten);
2887 Cvar_RegisterVariable(&r_bloom_blur);
2888 Cvar_RegisterVariable(&r_bloom_resolution);
2889 Cvar_RegisterVariable(&r_bloom_colorexponent);
2890 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2891 Cvar_RegisterVariable(&r_hdr);
2892 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2893 Cvar_RegisterVariable(&r_hdr_glowintensity);
2894 Cvar_RegisterVariable(&r_hdr_range);
2895 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2896 Cvar_RegisterVariable(&developer_texturelogging);
2897 Cvar_RegisterVariable(&gl_lightmaps);
2898 Cvar_RegisterVariable(&r_test);
2899 Cvar_RegisterVariable(&r_batchmode);
2900 Cvar_RegisterVariable(&r_glsl_saturation);
2901 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2902 Cvar_SetValue("r_fullbrights", 0);
2903 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2905 Cvar_RegisterVariable(&r_track_sprites);
2906 Cvar_RegisterVariable(&r_track_sprites_flags);
2907 Cvar_RegisterVariable(&r_track_sprites_scalew);
2908 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2911 extern void R_Textures_Init(void);
2912 extern void GL_Draw_Init(void);
2913 extern void GL_Main_Init(void);
2914 extern void R_Shadow_Init(void);
2915 extern void R_Sky_Init(void);
2916 extern void GL_Surf_Init(void);
2917 extern void R_Particles_Init(void);
2918 extern void R_Explosion_Init(void);
2919 extern void gl_backend_init(void);
2920 extern void Sbar_Init(void);
2921 extern void R_LightningBeams_Init(void);
2922 extern void Mod_RenderInit(void);
2924 void Render_Init(void)
2936 R_LightningBeams_Init();
2945 extern char *ENGINE_EXTENSIONS;
2948 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2949 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2950 gl_version = (const char *)qglGetString(GL_VERSION);
2951 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2955 if (!gl_platformextensions)
2956 gl_platformextensions = "";
2958 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2959 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2960 Con_Printf("GL_VERSION: %s\n", gl_version);
2961 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2962 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2964 VID_CheckExtensions();
2966 // LordHavoc: report supported extensions
2967 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2969 // clear to black (loading plaque will be seen over this)
2971 qglClearColor(0,0,0,1);CHECKGLERROR
2972 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2975 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2979 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2981 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2984 p = r_refdef.view.frustum + i;
2989 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2993 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2997 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3001 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3005 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3009 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3013 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3017 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3025 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3029 for (i = 0;i < numplanes;i++)
3036 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3040 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3044 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3048 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3052 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3056 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3060 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3064 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3072 //==================================================================================
3074 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3077 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3078 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3079 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3082 typedef struct r_animcache_entity_s
3089 qboolean wantnormals;
3090 qboolean wanttangents;
3092 r_animcache_entity_t;
3094 typedef struct r_animcache_s
3096 r_animcache_entity_t entity[MAX_EDICTS*2];
3102 static r_animcache_t r_animcachestate;
3104 void R_AnimCache_Free(void)
3107 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3109 r_animcachestate.entity[idx].maxvertices = 0;
3110 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3111 r_animcachestate.entity[idx].vertex3f = NULL;
3112 r_animcachestate.entity[idx].normal3f = NULL;
3113 r_animcachestate.entity[idx].svector3f = NULL;
3114 r_animcachestate.entity[idx].tvector3f = NULL;
3116 r_animcachestate.currentindex = 0;
3117 r_animcachestate.maxindex = 0;
3120 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3124 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3126 if (cache->maxvertices >= numvertices)
3129 // Release existing memory
3130 if (cache->vertex3f)
3131 Mem_Free(cache->vertex3f);
3133 // Pad by 1024 verts
3134 cache->maxvertices = (numvertices + 1023) & ~1023;
3135 arraySize = cache->maxvertices * 3;
3137 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3138 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3139 r_animcachestate.entity[cacheIdx].vertex3f = base;
3140 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3141 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3142 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3144 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3147 void R_AnimCache_NewFrame(void)
3151 if (r_animcache.integer && r_drawentities.integer)
3152 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3153 else if (r_animcachestate.maxindex)
3156 r_animcachestate.currentindex = 0;
3158 for (i = 0;i < r_refdef.scene.numentities;i++)
3159 r_refdef.scene.entities[i]->animcacheindex = -1;
3162 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3164 dp_model_t *model = ent->model;
3165 r_animcache_entity_t *c;
3166 // see if it's already cached this frame
3167 if (ent->animcacheindex >= 0)
3169 // add normals/tangents if needed
3170 c = r_animcachestate.entity + ent->animcacheindex;
3172 wantnormals = false;
3173 if (c->wanttangents)
3174 wanttangents = false;
3175 if (wantnormals || wanttangents)
3176 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3180 // see if this ent is worth caching
3181 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3183 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3185 // assign it a cache entry and make sure the arrays are big enough
3186 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3187 ent->animcacheindex = r_animcachestate.currentindex++;
3188 c = r_animcachestate.entity + ent->animcacheindex;
3189 c->wantnormals = wantnormals;
3190 c->wanttangents = wanttangents;
3191 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3196 void R_AnimCache_CacheVisibleEntities(void)
3199 qboolean wantnormals;
3200 qboolean wanttangents;
3202 if (!r_animcachestate.maxindex)
3205 wantnormals = !r_showsurfaces.integer;
3206 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3208 // TODO: thread this?
3210 for (i = 0;i < r_refdef.scene.numentities;i++)
3212 if (!r_refdef.viewcache.entityvisible[i])
3214 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3218 //==================================================================================
3220 static void R_View_UpdateEntityLighting (void)
3223 entity_render_t *ent;
3224 vec3_t tempdiffusenormal;
3226 for (i = 0;i < r_refdef.scene.numentities;i++)
3228 ent = r_refdef.scene.entities[i];
3230 // skip unseen models
3231 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3235 if (ent->model && ent->model->brush.num_leafs)
3237 // TODO: use modellight for r_ambient settings on world?
3238 VectorSet(ent->modellight_ambient, 0, 0, 0);
3239 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3240 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3244 // fetch the lighting from the worldmodel data
3245 VectorSet(ent->modellight_ambient, r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f));
3246 VectorClear(ent->modellight_diffuse);
3247 VectorClear(tempdiffusenormal);
3248 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3251 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3252 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3255 VectorSet(ent->modellight_ambient, 1, 1, 1);
3257 // move the light direction into modelspace coordinates for lighting code
3258 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3259 if(VectorLength2(ent->modellight_lightdir) == 0)
3260 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3261 VectorNormalize(ent->modellight_lightdir);
3265 static void R_View_UpdateEntityVisible (void)
3268 entity_render_t *ent;
3270 if (!r_drawentities.integer)
3273 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3274 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3276 // worldmodel can check visibility
3277 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3278 for (i = 0;i < r_refdef.scene.numentities;i++)
3280 ent = r_refdef.scene.entities[i];
3281 if (!(ent->flags & renderimask))
3282 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
3283 if ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
3284 r_refdef.viewcache.entityvisible[i] = true;
3286 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3288 for (i = 0;i < r_refdef.scene.numentities;i++)
3290 ent = r_refdef.scene.entities[i];
3291 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
3293 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.scene.worldmodel, r_refdef.view.origin, ent->mins, ent->maxs))
3294 ent->last_trace_visibility = realtime;
3295 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3296 r_refdef.viewcache.entityvisible[i] = 0;
3303 // no worldmodel or it can't check visibility
3304 for (i = 0;i < r_refdef.scene.numentities;i++)
3306 ent = r_refdef.scene.entities[i];
3307 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
3312 /// only used if skyrendermasked, and normally returns false
3313 int R_DrawBrushModelsSky (void)
3316 entity_render_t *ent;
3318 if (!r_drawentities.integer)
3322 for (i = 0;i < r_refdef.scene.numentities;i++)
3324 if (!r_refdef.viewcache.entityvisible[i])
3326 ent = r_refdef.scene.entities[i];
3327 if (!ent->model || !ent->model->DrawSky)
3329 ent->model->DrawSky(ent);
3335 static void R_DrawNoModel(entity_render_t *ent);
3336 static void R_DrawModels(void)
3339 entity_render_t *ent;
3341 if (!r_drawentities.integer)
3344 for (i = 0;i < r_refdef.scene.numentities;i++)
3346 if (!r_refdef.viewcache.entityvisible[i])
3348 ent = r_refdef.scene.entities[i];
3349 r_refdef.stats.entities++;
3350 if (ent->model && ent->model->Draw != NULL)
3351 ent->model->Draw(ent);
3357 static void R_DrawModelsDepth(void)
3360 entity_render_t *ent;
3362 if (!r_drawentities.integer)
3365 for (i = 0;i < r_refdef.scene.numentities;i++)
3367 if (!r_refdef.viewcache.entityvisible[i])
3369 ent = r_refdef.scene.entities[i];
3370 if (ent->model && ent->model->DrawDepth != NULL)
3371 ent->model->DrawDepth(ent);
3375 static void R_DrawModelsDebug(void)
3378 entity_render_t *ent;
3380 if (!r_drawentities.integer)
3383 for (i = 0;i < r_refdef.scene.numentities;i++)
3385 if (!r_refdef.viewcache.entityvisible[i])
3387 ent = r_refdef.scene.entities[i];
3388 if (ent->model && ent->model->DrawDebug != NULL)
3389 ent->model->DrawDebug(ent);
3393 static void R_DrawModelsAddWaterPlanes(void)
3396 entity_render_t *ent;
3398 if (!r_drawentities.integer)
3401 for (i = 0;i < r_refdef.scene.numentities;i++)
3403 if (!r_refdef.viewcache.entityvisible[i])
3405 ent = r_refdef.scene.entities[i];
3406 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3407 ent->model->DrawAddWaterPlanes(ent);
3411 static void R_View_SetFrustum(void)
3414 double slopex, slopey;
3415 vec3_t forward, left, up, origin;
3417 // we can't trust r_refdef.view.forward and friends in reflected scenes
3418 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3421 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3422 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3423 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3424 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3425 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3426 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3427 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3428 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3429 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3430 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3431 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3432 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3436 zNear = r_refdef.nearclip;
3437 nudge = 1.0 - 1.0 / (1<<23);
3438 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3439 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3440 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3441 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3442 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3443 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3444 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3445 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3451 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3452 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3453 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3454 r_refdef.view.frustum[0].dist = m[15] - m[12];
3456 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3457 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3458 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3459 r_refdef.view.frustum[1].dist = m[15] + m[12];
3461 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3462 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3463 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3464 r_refdef.view.frustum[2].dist = m[15] - m[13];
3466 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3467 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3468 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3469 r_refdef.view.frustum[3].dist = m[15] + m[13];
3471 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3472 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3473 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3474 r_refdef.view.frustum[4].dist = m[15] - m[14];
3476 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3477 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3478 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3479 r_refdef.view.frustum[5].dist = m[15] + m[14];
3482 if (r_refdef.view.useperspective)
3484 slopex = 1.0 / r_refdef.view.frustum_x;
3485 slopey = 1.0 / r_refdef.view.frustum_y;
3486 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3487 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3488 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3489 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3490 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3492 // Leaving those out was a mistake, those were in the old code, and they
3493 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3494 // I couldn't reproduce it after adding those normalizations. --blub
3495 VectorNormalize(r_refdef.view.frustum[0].normal);
3496 VectorNormalize(r_refdef.view.frustum[1].normal);
3497 VectorNormalize(r_refdef.view.frustum[2].normal);
3498 VectorNormalize(r_refdef.view.frustum[3].normal);
3500 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3501 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
3502 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
3503 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, 1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
3504 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * r_refdef.view.frustum_x, left, 1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
3506 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3507 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3508 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3509 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3510 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3514 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3515 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3516 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3517 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3518 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3519 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3520 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3521 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3522 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3523 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3525 r_refdef.view.numfrustumplanes = 5;
3527 if (r_refdef.view.useclipplane)
3529 r_refdef.view.numfrustumplanes = 6;
3530 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3533 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3534 PlaneClassify(r_refdef.view.frustum + i);
3536 // LordHavoc: note to all quake engine coders, Quake had a special case
3537 // for 90 degrees which assumed a square view (wrong), so I removed it,
3538 // Quake2 has it disabled as well.
3540 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3541 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3542 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3543 //PlaneClassify(&frustum[0]);
3545 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3546 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3547 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3548 //PlaneClassify(&frustum[1]);
3550 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3551 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3552 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3553 //PlaneClassify(&frustum[2]);
3555 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3556 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3557 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3558 //PlaneClassify(&frustum[3]);
3561 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3562 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3563 //PlaneClassify(&frustum[4]);
3566 void R_View_Update(void)
3568 R_View_SetFrustum();
3569 R_View_WorldVisibility(r_refdef.view.useclipplane);
3570 R_View_UpdateEntityVisible();
3571 R_View_UpdateEntityLighting();
3574 void R_SetupView(qboolean allowwaterclippingplane)
3576 const double *customclipplane = NULL;
3578 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3580 // LordHavoc: couldn't figure out how to make this approach the
3581 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3582 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3583 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3584 dist = r_refdef.view.clipplane.dist;
3585 plane[0] = r_refdef.view.clipplane.normal[0];
3586 plane[1] = r_refdef.view.clipplane.normal[1];
3587 plane[2] = r_refdef.view.clipplane.normal[2];
3589 customclipplane = plane;
3592 if (!r_refdef.view.useperspective)
3593 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
3594 else if (gl_stencil && r_useinfinitefarclip.integer)
3595 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
3597 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
3598 R_SetViewport(&r_refdef.view.viewport);
3601 void R_ResetViewRendering2D(void)
3603 r_viewport_t viewport;
3606 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3607 R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
3608 R_SetViewport(&viewport);
3609 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3610 GL_Color(1, 1, 1, 1);
3611 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3612 GL_BlendFunc(GL_ONE, GL_ZERO);
3613 GL_AlphaTest(false);
3614 GL_ScissorTest(false);
3615 GL_DepthMask(false);
3616 GL_DepthRange(0, 1);
3617 GL_DepthTest(false);
3618 R_Mesh_Matrix(&identitymatrix);
3619 R_Mesh_ResetTextureState();
3620 GL_PolygonOffset(0, 0);
3621 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3622 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3623 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3624 qglStencilMask(~0);CHECKGLERROR
3625 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3626 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3627 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3628 R_SetupGenericShader(true);
3631 void R_ResetViewRendering3D(void)
3636 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3637 GL_Color(1, 1, 1, 1);
3638 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3639 GL_BlendFunc(GL_ONE, GL_ZERO);
3640 GL_AlphaTest(false);
3641 GL_ScissorTest(true);
3643 GL_DepthRange(0, 1);
3645 R_Mesh_Matrix(&identitymatrix);
3646 R_Mesh_ResetTextureState();
3647 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3648 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3649 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3650 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3651 qglStencilMask(~0);CHECKGLERROR
3652 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3653 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3654 GL_CullFace(r_refdef.view.cullface_back);
3655 R_SetupGenericShader(true);
3658 void R_RenderScene(void);
3659 void R_RenderWaterPlanes(void);
3661 static void R_Water_StartFrame(void)
3664 int waterwidth, waterheight, texturewidth, textureheight;
3665 r_waterstate_waterplane_t *p;
3667 // set waterwidth and waterheight to the water resolution that will be
3668 // used (often less than the screen resolution for faster rendering)
3669 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3670 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3672 // calculate desired texture sizes
3673 // can't use water if the card does not support the texture size
3674 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3675 texturewidth = textureheight = waterwidth = waterheight = 0;
3676 else if (gl_support_arb_texture_non_power_of_two)
3678 texturewidth = waterwidth;
3679 textureheight = waterheight;
3683 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3684 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3687 // allocate textures as needed
3688 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3690 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3691 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3693 if (p->texture_refraction)
3694 R_FreeTexture(p->texture_refraction);
3695 p->texture_refraction = NULL;
3696 if (p->texture_reflection)
3697 R_FreeTexture(p->texture_reflection);
3698 p->texture_reflection = NULL;
3700 memset(&r_waterstate, 0, sizeof(r_waterstate));
3701 r_waterstate.texturewidth = texturewidth;
3702 r_waterstate.textureheight = textureheight;
3705 // when doing a reduced render (HDR) we want to use a smaller area
3706 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3707 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3709 if (r_waterstate.waterwidth)
3711 r_waterstate.enabled = true;
3713 // set up variables that will be used in shader setup
3714 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3715 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3716 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3717 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3720 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3721 r_waterstate.numwaterplanes = 0;
3724 void R_Water_AddWaterPlane(msurface_t *surface)
3726 int triangleindex, planeindex;
3732 r_waterstate_waterplane_t *p;
3733 texture_t *t = R_GetCurrentTexture(surface->texture);
3734 // just use the first triangle with a valid normal for any decisions
3735 VectorClear(normal);
3736 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3738 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3739 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3740 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3741 TriangleNormal(vert[0], vert[1], vert[2], normal);
3742 if (VectorLength2(normal) >= 0.001)
3746 VectorCopy(normal, plane.normal);
3747 VectorNormalize(plane.normal);
3748 plane.dist = DotProduct(vert[0], plane.normal);
3749 PlaneClassify(&plane);
3750 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3752 // skip backfaces (except if nocullface is set)
3753 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3755 VectorNegate(plane.normal, plane.normal);
3757 PlaneClassify(&plane);
3761 // find a matching plane if there is one
3762 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3763 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3765 if (planeindex >= r_waterstate.maxwaterplanes)
3766 return; // nothing we can do, out of planes
3768 // if this triangle does not fit any known plane rendered this frame, add one
3769 if (planeindex >= r_waterstate.numwaterplanes)
3771 // store the new plane
3772 r_waterstate.numwaterplanes++;
3774 // clear materialflags and pvs
3775 p->materialflags = 0;
3776 p->pvsvalid = false;
3778 // merge this surface's materialflags into the waterplane
3779 p->materialflags |= t->currentmaterialflags;
3780 // merge this surface's PVS into the waterplane
3781 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3782 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3783 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3785 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3790 static void R_Water_ProcessPlanes(void)
3792 r_refdef_view_t originalview;
3793 r_refdef_view_t myview;
3795 r_waterstate_waterplane_t *p;
3797 originalview = r_refdef.view;
3799 // make sure enough textures are allocated
3800 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3802 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3804 if (!p->texture_refraction)
3805 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);
3806 if (!p->texture_refraction)
3810 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3812 if (!p->texture_reflection)
3813 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);
3814 if (!p->texture_reflection)
3820 r_refdef.view = originalview;
3821 r_refdef.view.showdebug = false;
3822 r_refdef.view.width = r_waterstate.waterwidth;
3823 r_refdef.view.height = r_waterstate.waterheight;
3824 r_refdef.view.useclipplane = true;
3825 myview = r_refdef.view;
3826 r_waterstate.renderingscene = true;
3827 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3829 // render the normal view scene and copy into texture
3830 // (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)
3831 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3833 r_refdef.view = myview;
3834 r_refdef.view.clipplane = p->plane;
3835 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3836 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3837 PlaneClassify(&r_refdef.view.clipplane);
3839 R_ResetViewRendering3D();
3840 R_ClearScreen(r_refdef.fogenabled);
3844 // copy view into the screen texture
3845 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3846 GL_ActiveTexture(0);
3848 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
3851 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3853 r_refdef.view = myview;
3854 // render reflected scene and copy into texture
3855 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3856 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3857 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3858 r_refdef.view.clipplane = p->plane;
3859 // reverse the cullface settings for this render
3860 r_refdef.view.cullface_front = GL_FRONT;
3861 r_refdef.view.cullface_back = GL_BACK;
3862 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3864 r_refdef.view.usecustompvs = true;
3866 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3868 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3871 R_ResetViewRendering3D();
3872 R_ClearScreen(r_refdef.fogenabled);
3876 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3877 GL_ActiveTexture(0);
3879 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
3882 r_waterstate.renderingscene = false;
3883 r_refdef.view = originalview;
3884 R_ResetViewRendering3D();
3885 R_ClearScreen(r_refdef.fogenabled);
3889 r_refdef.view = originalview;
3890 r_waterstate.renderingscene = false;
3891 Cvar_SetValueQuick(&r_water, 0);
3892 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3896 void R_Bloom_StartFrame(void)
3898 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3900 // set bloomwidth and bloomheight to the bloom resolution that will be
3901 // used (often less than the screen resolution for faster rendering)
3902 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
3903 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
3904 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
3905 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
3906 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
3908 // calculate desired texture sizes
3909 if (gl_support_arb_texture_non_power_of_two)
3911 screentexturewidth = r_refdef.view.width;
3912 screentextureheight = r_refdef.view.height;
3913 bloomtexturewidth = r_bloomstate.bloomwidth;
3914 bloomtextureheight = r_bloomstate.bloomheight;
3918 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3919 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3920 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3921 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3924 if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
3926 Cvar_SetValueQuick(&r_hdr, 0);
3927 Cvar_SetValueQuick(&r_bloom, 0);
3928 Cvar_SetValueQuick(&r_motionblur, 0);
3929 Cvar_SetValueQuick(&r_damageblur, 0);
3932 if (!(r_glsl.integer && (r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
3933 screentexturewidth = screentextureheight = 0;
3934 if (!r_hdr.integer && !r_bloom.integer)
3935 bloomtexturewidth = bloomtextureheight = 0;
3937 // allocate textures as needed
3938 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3940 if (r_bloomstate.texture_screen)
3941 R_FreeTexture(r_bloomstate.texture_screen);
3942 r_bloomstate.texture_screen = NULL;
3943 r_bloomstate.screentexturewidth = screentexturewidth;
3944 r_bloomstate.screentextureheight = screentextureheight;
3945 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3946 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);
3948 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3950 if (r_bloomstate.texture_bloom)
3951 R_FreeTexture(r_bloomstate.texture_bloom);
3952 r_bloomstate.texture_bloom = NULL;
3953 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3954 r_bloomstate.bloomtextureheight = bloomtextureheight;
3955 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3956 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);
3959 // when doing a reduced render (HDR) we want to use a smaller area
3960 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
3961 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3962 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3963 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
3964 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
3966 // set up a texcoord array for the full resolution screen image
3967 // (we have to keep this around to copy back during final render)
3968 r_bloomstate.screentexcoord2f[0] = 0;
3969 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3970 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3971 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3972 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3973 r_bloomstate.screentexcoord2f[5] = 0;
3974 r_bloomstate.screentexcoord2f[6] = 0;
3975 r_bloomstate.screentexcoord2f[7] = 0;
3977 // set up a texcoord array for the reduced resolution bloom image
3978 // (which will be additive blended over the screen image)
3979 r_bloomstate.bloomtexcoord2f[0] = 0;
3980 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3981 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3982 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3983 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3984 r_bloomstate.bloomtexcoord2f[5] = 0;
3985 r_bloomstate.bloomtexcoord2f[6] = 0;
3986 r_bloomstate.bloomtexcoord2f[7] = 0;
3988 if (r_hdr.integer || r_bloom.integer)
3990 r_bloomstate.enabled = true;
3991 r_bloomstate.hdr = r_hdr.integer != 0;
3994 R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
3997 void R_Bloom_CopyBloomTexture(float colorscale)
3999 r_refdef.stats.bloom++;
4001 // scale down screen texture to the bloom texture size
4003 R_SetViewport(&r_bloomstate.viewport);
4004 GL_BlendFunc(GL_ONE, GL_ZERO);
4005 GL_Color(colorscale, colorscale, colorscale, 1);
4006 // TODO: optimize with multitexture or GLSL
4007 R_SetupGenericShader(true);
4008 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4009 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4010 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4011 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4013 // we now have a bloom image in the framebuffer
4014 // copy it into the bloom image texture for later processing
4015 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4016 GL_ActiveTexture(0);
4018 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4019 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4022 void R_Bloom_CopyHDRTexture(void)
4024 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4025 GL_ActiveTexture(0);
4027 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4028 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4031 void R_Bloom_MakeTexture(void)
4034 float xoffset, yoffset, r, brighten;
4036 r_refdef.stats.bloom++;
4038 R_ResetViewRendering2D();
4039 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4040 R_Mesh_ColorPointer(NULL, 0, 0);
4041 R_SetupGenericShader(true);
4043 // we have a bloom image in the framebuffer
4045 R_SetViewport(&r_bloomstate.viewport);
4047 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4050 r = bound(0, r_bloom_colorexponent.value / x, 1);
4051 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4052 GL_Color(r, r, r, 1);
4053 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4054 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4055 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4056 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4058 // copy the vertically blurred bloom view to a texture
4059 GL_ActiveTexture(0);
4061 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4062 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4065 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4066 brighten = r_bloom_brighten.value;
4068 brighten *= r_hdr_range.value;
4069 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4070 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4072 for (dir = 0;dir < 2;dir++)
4074 // blend on at multiple vertical offsets to achieve a vertical blur
4075 // TODO: do offset blends using GLSL
4076 GL_BlendFunc(GL_ONE, GL_ZERO);
4077 for (x = -range;x <= range;x++)
4079 if (!dir){xoffset = 0;yoffset = x;}
4080 else {xoffset = x;yoffset = 0;}
4081 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4082 yoffset /= (float)r_bloomstate.bloomtextureheight;
4083 // compute a texcoord array with the specified x and y offset
4084 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4085 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4086 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4087 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4088 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4089 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4090 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4091 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4092 // this r value looks like a 'dot' particle, fading sharply to
4093 // black at the edges
4094 // (probably not realistic but looks good enough)
4095 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4096 //r = (dir ? 1.0f : brighten)/(range*2+1);
4097 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
4098 GL_Color(r, r, r, 1);
4099 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4100 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4101 GL_BlendFunc(GL_ONE, GL_ONE);
4104 // copy the vertically blurred bloom view to a texture
4105 GL_ActiveTexture(0);
4107 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4108 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4111 // apply subtract last
4112 // (just like it would be in a GLSL shader)
4113 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4115 GL_BlendFunc(GL_ONE, GL_ZERO);
4116 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4117 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4118 GL_Color(1, 1, 1, 1);
4119 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4120 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4122 GL_BlendFunc(GL_ONE, GL_ONE);
4123 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4124 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4125 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4126 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4127 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4128 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4129 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4131 // copy the darkened bloom view to a texture
4132 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4133 GL_ActiveTexture(0);
4135 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4136 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4140 void R_HDR_RenderBloomTexture(void)
4142 int oldwidth, oldheight;
4143 float oldcolorscale;
4145 oldcolorscale = r_refdef.view.colorscale;
4146 oldwidth = r_refdef.view.width;
4147 oldheight = r_refdef.view.height;
4148 r_refdef.view.width = r_bloomstate.bloomwidth;
4149 r_refdef.view.height = r_bloomstate.bloomheight;
4151 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4152 // TODO: add exposure compensation features
4153 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4155 r_refdef.view.showdebug = false;
4156 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4158 R_ResetViewRendering3D();
4160 R_ClearScreen(r_refdef.fogenabled);
4161 if (r_timereport_active)
4162 R_TimeReport("HDRclear");
4165 if (r_timereport_active)
4166 R_TimeReport("visibility");
4168 // only do secondary renders with HDR if r_hdr is 2 or higher
4169 r_waterstate.numwaterplanes = 0;
4170 if (r_waterstate.enabled && r_hdr.integer >= 2)
4171 R_RenderWaterPlanes();
4173 r_refdef.view.showdebug = true;
4175 r_waterstate.numwaterplanes = 0;
4177 R_ResetViewRendering2D();
4179 R_Bloom_CopyHDRTexture();
4180 R_Bloom_MakeTexture();
4182 // restore the view settings
4183 r_refdef.view.width = oldwidth;
4184 r_refdef.view.height = oldheight;
4185 r_refdef.view.colorscale = oldcolorscale;
4187 R_ResetViewRendering3D();
4189 R_ClearScreen(r_refdef.fogenabled);
4190 if (r_timereport_active)
4191 R_TimeReport("viewclear");
4194 static void R_BlendView(void)
4196 if (r_bloomstate.texture_screen)
4198 // make sure the buffer is available
4199 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4201 R_ResetViewRendering2D();
4202 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4203 R_Mesh_ColorPointer(NULL, 0, 0);
4204 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4205 GL_ActiveTexture(0);CHECKGLERROR
4207 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4209 // declare variables
4211 static float avgspeed;
4213 speed = VectorLength(cl.movement_velocity);
4215 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4216 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4218 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4219 speed = bound(0, speed, 1);
4220 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4222 // calculate values into a standard alpha
4223 cl.motionbluralpha = 1 - exp(-
4225 (r_motionblur.value * speed / 80)
4227 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4230 max(0.0001, cl.time - cl.oldtime) // fps independent
4233 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4234 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4236 if (cl.motionbluralpha > 0)
4238 R_SetupGenericShader(true);
4239 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4240 GL_Color(1, 1, 1, cl.motionbluralpha);
4241 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4242 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4243 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4244 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4248 // copy view into the screen texture
4249 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);CHECKGLERROR
4250 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4253 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4255 unsigned int permutation =
4256 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4257 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4258 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4259 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4260 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4262 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4264 // render simple bloom effect
4265 // copy the screen and shrink it and darken it for the bloom process
4266 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4267 // make the bloom texture
4268 R_Bloom_MakeTexture();
4271 R_ResetViewRendering2D();
4272 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4273 R_Mesh_ColorPointer(NULL, 0, 0);
4274 GL_Color(1, 1, 1, 1);
4275 GL_BlendFunc(GL_ONE, GL_ZERO);
4276 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4277 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4278 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4279 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4280 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4281 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4282 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4283 if (r_glsl_permutation->loc_TintColor >= 0)
4284 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4285 if (r_glsl_permutation->loc_ClientTime >= 0)
4286 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4287 if (r_glsl_permutation->loc_PixelSize >= 0)
4288 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4289 if (r_glsl_permutation->loc_UserVec1 >= 0)
4291 float a=0, b=0, c=0, d=0;
4292 #if _MSC_VER >= 1400
4293 #define sscanf sscanf_s
4295 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4296 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4298 if (r_glsl_permutation->loc_UserVec2 >= 0)
4300 float a=0, b=0, c=0, d=0;
4301 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4302 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4304 if (r_glsl_permutation->loc_UserVec3 >= 0)
4306 float a=0, b=0, c=0, d=0;
4307 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4308 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4310 if (r_glsl_permutation->loc_UserVec4 >= 0)
4312 float a=0, b=0, c=0, d=0;
4313 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4314 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4316 if (r_glsl_permutation->loc_Saturation >= 0)
4317 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4318 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4319 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4325 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4327 // render high dynamic range bloom effect
4328 // the bloom texture was made earlier this render, so we just need to
4329 // blend it onto the screen...
4330 R_ResetViewRendering2D();
4331 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4332 R_Mesh_ColorPointer(NULL, 0, 0);
4333 R_SetupGenericShader(true);
4334 GL_Color(1, 1, 1, 1);
4335 GL_BlendFunc(GL_ONE, GL_ONE);
4336 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4337 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4338 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4339 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4341 else if (r_bloomstate.texture_bloom)
4343 // render simple bloom effect
4344 // copy the screen and shrink it and darken it for the bloom process
4345 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4346 // make the bloom texture
4347 R_Bloom_MakeTexture();
4348 // put the original screen image back in place and blend the bloom
4350 R_ResetViewRendering2D();
4351 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4352 R_Mesh_ColorPointer(NULL, 0, 0);
4353 GL_Color(1, 1, 1, 1);
4354 GL_BlendFunc(GL_ONE, GL_ZERO);
4355 // do both in one pass if possible
4356 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4357 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4358 if (r_textureunits.integer >= 2 && gl_combine.integer)
4360 R_SetupGenericTwoTextureShader(GL_ADD);
4361 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4362 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4366 R_SetupGenericShader(true);
4367 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4368 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4369 // now blend on the bloom texture
4370 GL_BlendFunc(GL_ONE, GL_ONE);
4371 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4372 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4374 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4375 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4377 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4379 // apply a color tint to the whole view
4380 R_ResetViewRendering2D();
4381 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4382 R_Mesh_ColorPointer(NULL, 0, 0);
4383 R_SetupGenericShader(false);
4384 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4385 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4386 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4390 matrix4x4_t r_waterscrollmatrix;
4392 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4394 if (r_refdef.fog_density)
4396 r_refdef.fogcolor[0] = r_refdef.fog_red;
4397 r_refdef.fogcolor[1] = r_refdef.fog_green;
4398 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4402 VectorCopy(r_refdef.fogcolor, fogvec);
4403 // color.rgb *= ContrastBoost * SceneBrightness;
4404 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4405 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4406 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4407 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4412 void R_UpdateVariables(void)
4416 r_refdef.scene.ambient = r_ambient.value;
4418 r_refdef.farclip = 4096;
4419 if (r_refdef.scene.worldmodel)
4420 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
4421 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4423 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4424 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4425 r_refdef.polygonfactor = 0;
4426 r_refdef.polygonoffset = 0;
4427 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4428 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4430 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4431 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4432 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4433 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4434 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4435 if (r_showsurfaces.integer)
4437 r_refdef.scene.rtworld = false;
4438 r_refdef.scene.rtworldshadows = false;
4439 r_refdef.scene.rtdlight = false;
4440 r_refdef.scene.rtdlightshadows = false;
4441 r_refdef.lightmapintensity = 0;
4444 if (gamemode == GAME_NEHAHRA)
4446 if (gl_fogenable.integer)
4448 r_refdef.oldgl_fogenable = true;
4449 r_refdef.fog_density = gl_fogdensity.value;
4450 r_refdef.fog_red = gl_fogred.value;
4451 r_refdef.fog_green = gl_foggreen.value;
4452 r_refdef.fog_blue = gl_fogblue.value;
4453 r_refdef.fog_alpha = 1;
4454 r_refdef.fog_start = 0;
4455 r_refdef.fog_end = gl_skyclip.value;
4457 else if (r_refdef.oldgl_fogenable)
4459 r_refdef.oldgl_fogenable = false;
4460 r_refdef.fog_density = 0;
4461 r_refdef.fog_red = 0;
4462 r_refdef.fog_green = 0;
4463 r_refdef.fog_blue = 0;
4464 r_refdef.fog_alpha = 0;
4465 r_refdef.fog_start = 0;
4466 r_refdef.fog_end = 0;
4470 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4471 r_refdef.fog_start = max(0, r_refdef.fog_start);
4472 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4474 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4476 if (r_refdef.fog_density && r_drawfog.integer)
4478 r_refdef.fogenabled = true;
4479 // this is the point where the fog reaches 0.9986 alpha, which we
4480 // consider a good enough cutoff point for the texture
4481 // (0.9986 * 256 == 255.6)
4482 if (r_fog_exp2.integer)
4483 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4485 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4486 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4487 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4488 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4489 // fog color was already set
4490 // update the fog texture
4491 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)
4492 R_BuildFogTexture();
4495 r_refdef.fogenabled = false;
4497 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4499 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4501 // build GLSL gamma texture
4502 #define RAMPWIDTH 256
4503 unsigned short ramp[RAMPWIDTH * 3];
4504 unsigned char rampbgr[RAMPWIDTH][4];
4507 r_texture_gammaramps_serial = vid_gammatables_serial;
4509 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4510 for(i = 0; i < RAMPWIDTH; ++i)
4512 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4513 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4514 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4517 if (r_texture_gammaramps)
4519 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4523 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
4529 // remove GLSL gamma texture
4533 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4534 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4540 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4541 if( scenetype != r_currentscenetype ) {
4542 // store the old scenetype
4543 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4544 r_currentscenetype = scenetype;
4545 // move in the new scene
4546 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4555 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4557 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4558 if( scenetype == r_currentscenetype ) {
4559 return &r_refdef.scene;
4561 return &r_scenes_store[ scenetype ];
4570 void R_RenderView(void)
4572 if (r_timereport_active)
4573 R_TimeReport("start");
4574 r_frame++; // used only by R_GetCurrentTexture
4575 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4577 R_AnimCache_NewFrame();
4579 if (r_refdef.view.isoverlay)
4581 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4582 GL_Clear( GL_DEPTH_BUFFER_BIT );
4583 R_TimeReport("depthclear");
4585 r_refdef.view.showdebug = false;
4587 r_waterstate.enabled = false;
4588 r_waterstate.numwaterplanes = 0;
4596 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4597 return; //Host_Error ("R_RenderView: NULL worldmodel");
4599 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4601 // break apart the view matrix into vectors for various purposes
4602 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4603 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4604 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4605 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4606 // make an inverted copy of the view matrix for tracking sprites
4607 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4609 R_Shadow_UpdateWorldLightSelection();
4611 R_Bloom_StartFrame();
4612 R_Water_StartFrame();
4615 if (r_timereport_active)
4616 R_TimeReport("viewsetup");
4618 R_ResetViewRendering3D();
4620 if (r_refdef.view.clear || r_refdef.fogenabled)
4622 R_ClearScreen(r_refdef.fogenabled);
4623 if (r_timereport_active)
4624 R_TimeReport("viewclear");
4626 r_refdef.view.clear = true;
4628 // this produces a bloom texture to be used in R_BlendView() later
4630 R_HDR_RenderBloomTexture();
4632 r_refdef.view.showdebug = true;
4635 if (r_timereport_active)
4636 R_TimeReport("visibility");
4638 r_waterstate.numwaterplanes = 0;
4639 if (r_waterstate.enabled)
4640 R_RenderWaterPlanes();
4643 r_waterstate.numwaterplanes = 0;
4646 if (r_timereport_active)
4647 R_TimeReport("blendview");
4649 GL_Scissor(0, 0, vid.width, vid.height);
4650 GL_ScissorTest(false);
4654 void R_RenderWaterPlanes(void)
4656 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4658 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4659 if (r_timereport_active)
4660 R_TimeReport("waterworld");
4663 // don't let sound skip if going slow
4664 if (r_refdef.scene.extraupdate)
4667 R_DrawModelsAddWaterPlanes();
4668 if (r_timereport_active)
4669 R_TimeReport("watermodels");
4671 if (r_waterstate.numwaterplanes)
4673 R_Water_ProcessPlanes();
4674 if (r_timereport_active)
4675 R_TimeReport("waterscenes");
4679 extern void R_DrawLightningBeams (void);
4680 extern void VM_CL_AddPolygonsToMeshQueue (void);
4681 extern void R_DrawPortals (void);
4682 extern cvar_t cl_locs_show;
4683 static void R_DrawLocs(void);
4684 static void R_DrawEntityBBoxes(void);
4685 void R_RenderScene(void)
4687 r_refdef.stats.renders++;
4691 // don't let sound skip if going slow
4692 if (r_refdef.scene.extraupdate)
4695 R_MeshQueue_BeginScene();
4699 Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
4701 if (cl.csqc_vidvars.drawworld)
4703 // don't let sound skip if going slow
4704 if (r_refdef.scene.extraupdate)
4707 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4709 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4710 if (r_timereport_active)
4711 R_TimeReport("worldsky");
4714 if (R_DrawBrushModelsSky() && r_timereport_active)
4715 R_TimeReport("bmodelsky");
4718 R_AnimCache_CacheVisibleEntities();
4720 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4722 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4723 if (r_timereport_active)
4724 R_TimeReport("worlddepth");
4726 if (r_depthfirst.integer >= 2)
4728 R_DrawModelsDepth();
4729 if (r_timereport_active)
4730 R_TimeReport("modeldepth");
4733 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4735 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4736 if (r_timereport_active)
4737 R_TimeReport("world");
4740 // don't let sound skip if going slow
4741 if (r_refdef.scene.extraupdate)
4745 if (r_timereport_active)
4746 R_TimeReport("models");
4748 // don't let sound skip if going slow
4749 if (r_refdef.scene.extraupdate)
4752 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4754 R_DrawModelShadows();
4755 R_ResetViewRendering3D();
4756 // don't let sound skip if going slow
4757 if (r_refdef.scene.extraupdate)
4761 R_ShadowVolumeLighting(false);
4762 if (r_timereport_active)
4763 R_TimeReport("rtlights");
4765 // don't let sound skip if going slow
4766 if (r_refdef.scene.extraupdate)
4769 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4771 R_DrawModelShadows();
4772 R_ResetViewRendering3D();
4773 // don't let sound skip if going slow
4774 if (r_refdef.scene.extraupdate)
4778 if (cl.csqc_vidvars.drawworld)
4780 R_DrawLightningBeams();
4781 if (r_timereport_active)
4782 R_TimeReport("lightning");
4785 if (r_timereport_active)
4786 R_TimeReport("decals");
4789 if (r_timereport_active)
4790 R_TimeReport("particles");
4793 if (r_timereport_active)
4794 R_TimeReport("explosions");
4797 R_SetupGenericShader(true);
4798 VM_CL_AddPolygonsToMeshQueue();
4800 if (r_refdef.view.showdebug)
4802 if (cl_locs_show.integer)
4805 if (r_timereport_active)
4806 R_TimeReport("showlocs");
4809 if (r_drawportals.integer)
4812 if (r_timereport_active)
4813 R_TimeReport("portals");
4816 if (r_showbboxes.value > 0)
4818 R_DrawEntityBBoxes();
4819 if (r_timereport_active)
4820 R_TimeReport("bboxes");
4824 R_SetupGenericShader(true);
4825 R_MeshQueue_RenderTransparent();
4826 if (r_timereport_active)
4827 R_TimeReport("drawtrans");
4829 R_SetupGenericShader(true);
4831 if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0))
4833 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4834 if (r_timereport_active)
4835 R_TimeReport("worlddebug");
4836 R_DrawModelsDebug();
4837 if (r_timereport_active)
4838 R_TimeReport("modeldebug");
4841 R_SetupGenericShader(true);
4843 if (cl.csqc_vidvars.drawworld)
4846 if (r_timereport_active)
4847 R_TimeReport("coronas");
4850 // don't let sound skip if going slow
4851 if (r_refdef.scene.extraupdate)
4854 R_ResetViewRendering2D();
4857 static const unsigned short bboxelements[36] =
4867 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4870 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4871 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4872 GL_DepthMask(false);
4873 GL_DepthRange(0, 1);
4874 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4875 R_Mesh_Matrix(&identitymatrix);
4876 R_Mesh_ResetTextureState();
4878 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4879 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4880 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4881 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4882 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4883 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4884 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4885 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4886 R_FillColors(color4f, 8, cr, cg, cb, ca);
4887 if (r_refdef.fogenabled)
4889 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4891 f1 = FogPoint_World(v);
4893 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4894 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4895 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4898 R_Mesh_VertexPointer(vertex3f, 0, 0);
4899 R_Mesh_ColorPointer(color4f, 0, 0);
4900 R_Mesh_ResetTextureState();
4901 R_SetupGenericShader(false);
4902 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4905 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4909 prvm_edict_t *edict;
4910 prvm_prog_t *prog_save = prog;
4912 // this function draws bounding boxes of server entities
4916 GL_CullFace(GL_NONE);
4917 R_SetupGenericShader(false);
4921 for (i = 0;i < numsurfaces;i++)
4923 edict = PRVM_EDICT_NUM(surfacelist[i]);
4924 switch ((int)edict->fields.server->solid)
4926 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4927 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4928 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4929 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4930 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4931 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4933 color[3] *= r_showbboxes.value;
4934 color[3] = bound(0, color[3], 1);
4935 GL_DepthTest(!r_showdisabledepthtest.integer);
4936 GL_CullFace(r_refdef.view.cullface_front);
4937 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4943 static void R_DrawEntityBBoxes(void)
4946 prvm_edict_t *edict;
4948 prvm_prog_t *prog_save = prog;
4950 // this function draws bounding boxes of server entities
4956 for (i = 0;i < prog->num_edicts;i++)
4958 edict = PRVM_EDICT_NUM(i);
4959 if (edict->priv.server->free)
4961 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4962 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4964 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4966 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4967 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4973 unsigned short nomodelelements[24] =
4985 float nomodelvertex3f[6*3] =
4995 float nomodelcolor4f[6*4] =
4997 0.0f, 0.0f, 0.5f, 1.0f,
4998 0.0f, 0.0f, 0.5f, 1.0f,
4999 0.0f, 0.5f, 0.0f, 1.0f,
5000 0.0f, 0.5f, 0.0f, 1.0f,
5001 0.5f, 0.0f, 0.0f, 1.0f,
5002 0.5f, 0.0f, 0.0f, 1.0f
5005 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5010 // this is only called once per entity so numsurfaces is always 1, and
5011 // surfacelist is always {0}, so this code does not handle batches
5012 R_Mesh_Matrix(&ent->matrix);
5014 if (ent->flags & EF_ADDITIVE)
5016 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5017 GL_DepthMask(false);
5019 else if (ent->alpha < 1)
5021 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5022 GL_DepthMask(false);
5026 GL_BlendFunc(GL_ONE, GL_ZERO);
5029 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5030 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5031 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
5032 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5033 R_SetupGenericShader(false);
5034 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
5035 if (r_refdef.fogenabled)
5038 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5039 R_Mesh_ColorPointer(color4f, 0, 0);
5040 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5041 f1 = FogPoint_World(org);
5043 for (i = 0, c = color4f;i < 6;i++, c += 4)
5045 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5046 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5047 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5051 else if (ent->alpha != 1)
5053 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5054 R_Mesh_ColorPointer(color4f, 0, 0);
5055 for (i = 0, c = color4f;i < 6;i++, c += 4)
5059 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
5060 R_Mesh_ResetTextureState();
5061 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
5064 void R_DrawNoModel(entity_render_t *ent)
5067 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5068 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
5069 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5071 // R_DrawNoModelCallback(ent, 0);
5074 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5076 vec3_t right1, right2, diff, normal;
5078 VectorSubtract (org2, org1, normal);
5080 // calculate 'right' vector for start
5081 VectorSubtract (r_refdef.view.origin, org1, diff);
5082 CrossProduct (normal, diff, right1);
5083 VectorNormalize (right1);
5085 // calculate 'right' vector for end
5086 VectorSubtract (r_refdef.view.origin, org2, diff);
5087 CrossProduct (normal, diff, right2);
5088 VectorNormalize (right2);
5090 vert[ 0] = org1[0] + width * right1[0];
5091 vert[ 1] = org1[1] + width * right1[1];
5092 vert[ 2] = org1[2] + width * right1[2];
5093 vert[ 3] = org1[0] - width * right1[0];
5094 vert[ 4] = org1[1] - width * right1[1];
5095 vert[ 5] = org1[2] - width * right1[2];
5096 vert[ 6] = org2[0] - width * right2[0];
5097 vert[ 7] = org2[1] - width * right2[1];
5098 vert[ 8] = org2[2] - width * right2[2];
5099 vert[ 9] = org2[0] + width * right2[0];
5100 vert[10] = org2[1] + width * right2[1];
5101 vert[11] = org2[2] + width * right2[2];
5104 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
5106 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)
5108 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
5112 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
5113 fog = FogPoint_World(origin);
5115 R_Mesh_Matrix(&identitymatrix);
5116 GL_BlendFunc(blendfunc1, blendfunc2);
5118 GL_CullFace(GL_NONE);
5120 GL_DepthMask(false);
5121 GL_DepthRange(0, depthshort ? 0.0625 : 1);
5122 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5123 GL_DepthTest(!depthdisable);
5125 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5126 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5127 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5128 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5129 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5130 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5131 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5132 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5133 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5134 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5135 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5136 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5138 R_Mesh_VertexPointer(vertex3f, 0, 0);
5139 R_Mesh_ColorPointer(NULL, 0, 0);
5140 R_Mesh_ResetTextureState();
5141 R_SetupGenericShader(true);
5142 R_Mesh_TexBind(0, R_GetTexture(texture));
5143 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
5144 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
5145 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
5146 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5148 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
5150 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
5151 GL_BlendFunc(blendfunc1, GL_ONE);
5153 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
5154 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5158 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5163 VectorSet(v, x, y, z);
5164 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5165 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5167 if (i == mesh->numvertices)
5169 if (mesh->numvertices < mesh->maxvertices)
5171 VectorCopy(v, vertex3f);
5172 mesh->numvertices++;
5174 return mesh->numvertices;
5180 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5184 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5185 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5186 e = mesh->element3i + mesh->numtriangles * 3;
5187 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5189 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5190 if (mesh->numtriangles < mesh->maxtriangles)
5195 mesh->numtriangles++;
5197 element[1] = element[2];
5201 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5205 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5206 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5207 e = mesh->element3i + mesh->numtriangles * 3;
5208 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5210 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5211 if (mesh->numtriangles < mesh->maxtriangles)
5216 mesh->numtriangles++;
5218 element[1] = element[2];
5222 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5223 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5225 int planenum, planenum2;
5228 mplane_t *plane, *plane2;
5230 double temppoints[2][256*3];
5231 // figure out how large a bounding box we need to properly compute this brush
5233 for (w = 0;w < numplanes;w++)
5234 maxdist = max(maxdist, planes[w].dist);
5235 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5236 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5237 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5241 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5242 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5244 if (planenum2 == planenum)
5246 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);
5249 if (tempnumpoints < 3)
5251 // generate elements forming a triangle fan for this polygon
5252 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5256 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)
5258 texturelayer_t *layer;
5259 layer = t->currentlayers + t->currentnumlayers++;
5261 layer->depthmask = depthmask;
5262 layer->blendfunc1 = blendfunc1;
5263 layer->blendfunc2 = blendfunc2;
5264 layer->texture = texture;
5265 layer->texmatrix = *matrix;
5266 layer->color[0] = r * r_refdef.view.colorscale;
5267 layer->color[1] = g * r_refdef.view.colorscale;
5268 layer->color[2] = b * r_refdef.view.colorscale;
5269 layer->color[3] = a;
5272 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5275 index = parms[2] + r_refdef.scene.time * parms[3];
5276 index -= floor(index);
5280 case Q3WAVEFUNC_NONE:
5281 case Q3WAVEFUNC_NOISE:
5282 case Q3WAVEFUNC_COUNT:
5285 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5286 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5287 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5288 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5289 case Q3WAVEFUNC_TRIANGLE:
5291 f = index - floor(index);
5302 return (float)(parms[0] + parms[1] * f);
5305 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5310 matrix4x4_t matrix, temp;
5311 switch(tcmod->tcmod)
5315 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5316 matrix = r_waterscrollmatrix;
5318 matrix = identitymatrix;
5320 case Q3TCMOD_ENTITYTRANSLATE:
5321 // this is used in Q3 to allow the gamecode to control texcoord
5322 // scrolling on the entity, which is not supported in darkplaces yet.
5323 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5325 case Q3TCMOD_ROTATE:
5326 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5327 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5328 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5331 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5333 case Q3TCMOD_SCROLL:
5334 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5336 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5337 w = (int) tcmod->parms[0];
5338 h = (int) tcmod->parms[1];
5339 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5341 idx = (int) floor(f * w * h);
5342 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5344 case Q3TCMOD_STRETCH:
5345 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5346 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5348 case Q3TCMOD_TRANSFORM:
5349 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5350 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5351 VectorSet(tcmat + 6, 0 , 0 , 1);
5352 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5353 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5355 case Q3TCMOD_TURBULENT:
5356 // this is handled in the RSurf_PrepareVertices function
5357 matrix = identitymatrix;
5361 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5364 texture_t *R_GetCurrentTexture(texture_t *t)
5367 const entity_render_t *ent = rsurface.entity;
5368 dp_model_t *model = ent->model;
5369 q3shaderinfo_layer_tcmod_t *tcmod;
5371 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5372 return t->currentframe;
5373 t->update_lastrenderframe = r_frame;
5374 t->update_lastrenderentity = (void *)ent;
5376 // switch to an alternate material if this is a q1bsp animated material
5378 texture_t *texture = t;
5379 int s = ent->skinnum;
5380 if ((unsigned int)s >= (unsigned int)model->numskins)
5382 if (model->skinscenes)
5384 if (model->skinscenes[s].framecount > 1)
5385 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5387 s = model->skinscenes[s].firstframe;
5390 t = t + s * model->num_surfaces;
5393 // use an alternate animation if the entity's frame is not 0,
5394 // and only if the texture has an alternate animation
5395 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
5396 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5398 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5400 texture->currentframe = t;
5403 // update currentskinframe to be a qw skin or animation frame
5404 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[i].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl"))
5406 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
5408 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
5409 if (developer_loading.integer)
5410 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
5411 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);
5413 t->currentskinframe = r_qwskincache_skinframe[i];
5414 if (t->currentskinframe == NULL)
5415 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5417 else if (t->numskinframes >= 2)
5418 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5419 if (t->backgroundnumskinframes >= 2)
5420 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
5422 t->currentmaterialflags = t->basematerialflags;
5423 t->currentalpha = ent->alpha;
5424 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5425 t->currentalpha *= r_wateralpha.value;
5426 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5427 t->currentalpha *= t->r_water_wateralpha;
5428 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5429 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5430 if (!(ent->flags & RENDER_LIGHT))
5431 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5432 else if (rsurface.modeltexcoordlightmap2f == NULL)
5434 // pick a model lighting mode
5435 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
5436 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5438 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5440 if (ent->effects & EF_ADDITIVE)
5441 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5442 else if (t->currentalpha < 1)
5443 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5444 if (ent->effects & EF_DOUBLESIDED)
5445 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5446 if (ent->effects & EF_NODEPTHTEST)
5447 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5448 if (ent->flags & RENDER_VIEWMODEL)
5449 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5450 if (t->backgroundnumskinframes)
5451 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5452 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5454 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5455 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5458 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5460 // there is no tcmod
5461 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5463 t->currenttexmatrix = r_waterscrollmatrix;
5464 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5468 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5469 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5472 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5473 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5474 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5475 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5477 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5478 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5479 t->glosstexture = r_texture_black;
5480 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5481 t->backgroundglosstexture = r_texture_black;
5482 t->specularpower = r_shadow_glossexponent.value;
5483 // TODO: store reference values for these in the texture?
5484 t->specularscale = 0;
5485 if (r_shadow_gloss.integer > 0)
5487 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5489 if (r_shadow_glossintensity.value > 0)
5491 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5492 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5493 t->specularscale = r_shadow_glossintensity.value;
5496 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5498 t->glosstexture = r_texture_white;
5499 t->backgroundglosstexture = r_texture_white;
5500 t->specularscale = r_shadow_gloss2intensity.value;
5504 // lightmaps mode looks bad with dlights using actual texturing, so turn
5505 // off the colormap and glossmap, but leave the normalmap on as it still
5506 // accurately represents the shading involved
5507 if (gl_lightmaps.integer)
5509 t->basetexture = r_texture_grey128;
5510 t->backgroundbasetexture = NULL;
5511 t->specularscale = 0;
5512 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5515 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5516 VectorClear(t->dlightcolor);
5517 t->currentnumlayers = 0;
5518 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5521 int blendfunc1, blendfunc2;
5523 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5525 blendfunc1 = GL_SRC_ALPHA;
5526 blendfunc2 = GL_ONE;
5528 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5530 blendfunc1 = GL_SRC_ALPHA;
5531 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5533 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5535 blendfunc1 = t->customblendfunc[0];
5536 blendfunc2 = t->customblendfunc[1];
5540 blendfunc1 = GL_ONE;
5541 blendfunc2 = GL_ZERO;
5543 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5544 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5545 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5546 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5548 // fullbright is not affected by r_refdef.lightmapintensity
5549 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
5550 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5551 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5552 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5553 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5557 vec3_t ambientcolor;
5559 // set the color tint used for lights affecting this surface
5560 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5562 // q3bsp has no lightmap updates, so the lightstylevalue that
5563 // would normally be baked into the lightmap must be
5564 // applied to the color
5565 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5566 if (ent->model->type == mod_brushq3)
5567 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5568 colorscale *= r_refdef.lightmapintensity;
5569 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5570 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5571 // basic lit geometry
5572 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
5573 // add pants/shirt if needed
5574 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5575 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5576 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5577 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
5578 // now add ambient passes if needed
5579 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5581 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
5582 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5583 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
5584 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5585 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
5588 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5589 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->lightmapcolor[3]);
5590 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5592 // if this is opaque use alpha blend which will darken the earlier
5595 // if this is an alpha blended material, all the earlier passes
5596 // were darkened by fog already, so we only need to add the fog
5597 // color ontop through the fog mask texture
5599 // if this is an additive blended material, all the earlier passes
5600 // were darkened by fog already, and we should not add fog color
5601 // (because the background was not darkened, there is no fog color
5602 // that was lost behind it).
5603 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0] / r_refdef.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]);
5607 return t->currentframe;
5610 rsurfacestate_t rsurface;
5612 void R_Mesh_ResizeArrays(int newvertices)
5615 if (rsurface.array_size >= newvertices)
5617 if (rsurface.array_modelvertex3f)
5618 Mem_Free(rsurface.array_modelvertex3f);
5619 rsurface.array_size = (newvertices + 1023) & ~1023;
5620 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5621 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5622 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5623 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5624 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5625 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5626 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5627 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5628 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5629 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5630 rsurface.array_color4f = base + rsurface.array_size * 27;
5631 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5634 void RSurf_ActiveWorldEntity(void)
5636 dp_model_t *model = r_refdef.scene.worldmodel;
5637 //if (rsurface.entity == r_refdef.scene.worldentity)
5639 rsurface.entity = r_refdef.scene.worldentity;
5640 if (rsurface.array_size < model->surfmesh.num_vertices)
5641 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5642 rsurface.matrix = identitymatrix;
5643 rsurface.inversematrix = identitymatrix;
5644 R_Mesh_Matrix(&identitymatrix);
5645 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5646 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5647 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5648 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5649 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5650 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5651 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5652 rsurface.frameblend[0].lerp = 1;
5653 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5654 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5655 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5656 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5657 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5658 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5659 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5660 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5661 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5662 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5663 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5664 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5665 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5666 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5667 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5668 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5669 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5670 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5671 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5672 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5673 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5674 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5675 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5676 rsurface.modelelement3i = model->surfmesh.data_element3i;
5677 rsurface.modelelement3s = model->surfmesh.data_element3s;
5678 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5679 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5680 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5681 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5682 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5683 rsurface.modelsurfaces = model->data_surfaces;
5684 rsurface.generatedvertex = false;
5685 rsurface.vertex3f = rsurface.modelvertex3f;
5686 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5687 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5688 rsurface.svector3f = rsurface.modelsvector3f;
5689 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5690 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5691 rsurface.tvector3f = rsurface.modeltvector3f;
5692 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5693 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5694 rsurface.normal3f = rsurface.modelnormal3f;
5695 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5696 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5697 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5700 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5702 dp_model_t *model = ent->model;
5703 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5705 rsurface.entity = (entity_render_t *)ent;
5706 if (rsurface.array_size < model->surfmesh.num_vertices)
5707 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5708 rsurface.matrix = ent->matrix;
5709 rsurface.inversematrix = ent->inversematrix;
5710 R_Mesh_Matrix(&rsurface.matrix);
5711 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5712 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5713 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5714 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5715 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5716 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5717 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5718 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5719 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5720 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5721 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5722 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5723 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5724 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5725 if (ent->model->brush.submodel)
5727 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5728 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5730 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5732 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5734 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5735 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5736 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5737 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5739 else if (wanttangents)
5741 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5742 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5743 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5744 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5745 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5747 else if (wantnormals)
5749 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5750 rsurface.modelsvector3f = NULL;
5751 rsurface.modeltvector3f = NULL;
5752 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5753 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5757 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5758 rsurface.modelsvector3f = NULL;
5759 rsurface.modeltvector3f = NULL;
5760 rsurface.modelnormal3f = NULL;
5761 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5763 rsurface.modelvertex3f_bufferobject = 0;
5764 rsurface.modelvertex3f_bufferoffset = 0;
5765 rsurface.modelsvector3f_bufferobject = 0;
5766 rsurface.modelsvector3f_bufferoffset = 0;
5767 rsurface.modeltvector3f_bufferobject = 0;
5768 rsurface.modeltvector3f_bufferoffset = 0;
5769 rsurface.modelnormal3f_bufferobject = 0;
5770 rsurface.modelnormal3f_bufferoffset = 0;
5771 rsurface.generatedvertex = true;
5775 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5776 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5777 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5778 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5779 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5780 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5781 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5782 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5783 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5784 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5785 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5786 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5787 rsurface.generatedvertex = false;
5789 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5790 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5791 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5792 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5793 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5794 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5795 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5796 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5797 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5798 rsurface.modelelement3i = model->surfmesh.data_element3i;
5799 rsurface.modelelement3s = model->surfmesh.data_element3s;
5800 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5801 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5802 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5803 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5804 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5805 rsurface.modelsurfaces = model->data_surfaces;
5806 rsurface.vertex3f = rsurface.modelvertex3f;
5807 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5808 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5809 rsurface.svector3f = rsurface.modelsvector3f;
5810 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5811 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5812 rsurface.tvector3f = rsurface.modeltvector3f;
5813 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5814 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5815 rsurface.normal3f = rsurface.modelnormal3f;
5816 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5817 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5818 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5821 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5822 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5825 int texturesurfaceindex;
5830 const float *v1, *in_tc;
5832 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5834 q3shaderinfo_deform_t *deform;
5835 // 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
5836 if (rsurface.generatedvertex)
5838 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5839 generatenormals = true;
5840 for (i = 0;i < Q3MAXDEFORMS;i++)
5842 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5844 generatetangents = true;
5845 generatenormals = true;
5847 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5848 generatenormals = true;
5850 if (generatenormals && !rsurface.modelnormal3f)
5852 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5853 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5854 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5855 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
5857 if (generatetangents && !rsurface.modelsvector3f)
5859 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5860 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5861 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5862 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5863 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5864 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5865 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 != 0);
5868 rsurface.vertex3f = rsurface.modelvertex3f;
5869 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5870 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5871 rsurface.svector3f = rsurface.modelsvector3f;
5872 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5873 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5874 rsurface.tvector3f = rsurface.modeltvector3f;
5875 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5876 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5877 rsurface.normal3f = rsurface.modelnormal3f;
5878 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5879 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5880 // if vertices are deformed (sprite flares and things in maps, possibly
5881 // water waves, bulges and other deformations), generate them into
5882 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5883 // (may be static model data or generated data for an animated model, or
5884 // the previous deform pass)
5885 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5887 switch (deform->deform)
5890 case Q3DEFORM_PROJECTIONSHADOW:
5891 case Q3DEFORM_TEXT0:
5892 case Q3DEFORM_TEXT1:
5893 case Q3DEFORM_TEXT2:
5894 case Q3DEFORM_TEXT3:
5895 case Q3DEFORM_TEXT4:
5896 case Q3DEFORM_TEXT5:
5897 case Q3DEFORM_TEXT6:
5898 case Q3DEFORM_TEXT7:
5901 case Q3DEFORM_AUTOSPRITE:
5902 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5903 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5904 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5905 VectorNormalize(newforward);
5906 VectorNormalize(newright);
5907 VectorNormalize(newup);
5908 // make deformed versions of only the model vertices used by the specified surfaces
5909 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5911 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5912 // a single autosprite surface can contain multiple sprites...
5913 for (j = 0;j < surface->num_vertices - 3;j += 4)
5915 VectorClear(center);
5916 for (i = 0;i < 4;i++)
5917 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5918 VectorScale(center, 0.25f, center);
5919 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5920 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5921 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5922 for (i = 0;i < 4;i++)
5924 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5925 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5928 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 != 0);
5929 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 != 0);
5931 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5932 rsurface.vertex3f_bufferobject = 0;
5933 rsurface.vertex3f_bufferoffset = 0;
5934 rsurface.svector3f = rsurface.array_deformedsvector3f;
5935 rsurface.svector3f_bufferobject = 0;
5936 rsurface.svector3f_bufferoffset = 0;
5937 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5938 rsurface.tvector3f_bufferobject = 0;
5939 rsurface.tvector3f_bufferoffset = 0;
5940 rsurface.normal3f = rsurface.array_deformednormal3f;
5941 rsurface.normal3f_bufferobject = 0;
5942 rsurface.normal3f_bufferoffset = 0;
5944 case Q3DEFORM_AUTOSPRITE2:
5945 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5946 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5947 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5948 VectorNormalize(newforward);
5949 VectorNormalize(newright);
5950 VectorNormalize(newup);
5951 // make deformed versions of only the model vertices used by the specified surfaces
5952 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5954 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5955 const float *v1, *v2;
5965 memset(shortest, 0, sizeof(shortest));
5966 // a single autosprite surface can contain multiple sprites...
5967 for (j = 0;j < surface->num_vertices - 3;j += 4)
5969 VectorClear(center);
5970 for (i = 0;i < 4;i++)
5971 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5972 VectorScale(center, 0.25f, center);
5973 // find the two shortest edges, then use them to define the
5974 // axis vectors for rotating around the central axis
5975 for (i = 0;i < 6;i++)
5977 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5978 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5980 Debug_PolygonBegin(NULL, 0);
5981 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5982 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);
5983 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5986 l = VectorDistance2(v1, v2);
5987 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5989 l += (1.0f / 1024.0f);
5990 if (shortest[0].length2 > l || i == 0)
5992 shortest[1] = shortest[0];
5993 shortest[0].length2 = l;
5994 shortest[0].v1 = v1;
5995 shortest[0].v2 = v2;
5997 else if (shortest[1].length2 > l || i == 1)
5999 shortest[1].length2 = l;
6000 shortest[1].v1 = v1;
6001 shortest[1].v2 = v2;
6004 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6005 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6007 Debug_PolygonBegin(NULL, 0);
6008 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6009 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);
6010 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6013 // this calculates the right vector from the shortest edge
6014 // and the up vector from the edge midpoints
6015 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6016 VectorNormalize(right);
6017 VectorSubtract(end, start, up);
6018 VectorNormalize(up);
6019 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6020 VectorSubtract(rsurface.modelorg, center, forward);
6021 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6022 VectorNegate(forward, forward);
6023 VectorReflect(forward, 0, up, forward);
6024 VectorNormalize(forward);
6025 CrossProduct(up, forward, newright);
6026 VectorNormalize(newright);
6028 Debug_PolygonBegin(NULL, 0);
6029 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);
6030 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6031 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6035 Debug_PolygonBegin(NULL, 0);
6036 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6037 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6038 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6041 // rotate the quad around the up axis vector, this is made
6042 // especially easy by the fact we know the quad is flat,
6043 // so we only have to subtract the center position and
6044 // measure distance along the right vector, and then
6045 // multiply that by the newright vector and add back the
6047 // we also need to subtract the old position to undo the
6048 // displacement from the center, which we do with a
6049 // DotProduct, the subtraction/addition of center is also
6050 // optimized into DotProducts here
6051 l = DotProduct(right, center);
6052 for (i = 0;i < 4;i++)
6054 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6055 f = DotProduct(right, v1) - l;
6056 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6059 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 != 0);
6060 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 != 0);
6062 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6063 rsurface.vertex3f_bufferobject = 0;
6064 rsurface.vertex3f_bufferoffset = 0;
6065 rsurface.svector3f = rsurface.array_deformedsvector3f;
6066 rsurface.svector3f_bufferobject = 0;
6067 rsurface.svector3f_bufferoffset = 0;
6068 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6069 rsurface.tvector3f_bufferobject = 0;
6070 rsurface.tvector3f_bufferoffset = 0;
6071 rsurface.normal3f = rsurface.array_deformednormal3f;
6072 rsurface.normal3f_bufferobject = 0;
6073 rsurface.normal3f_bufferoffset = 0;
6075 case Q3DEFORM_NORMAL:
6076 // deform the normals to make reflections wavey
6077 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6079 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6080 for (j = 0;j < surface->num_vertices;j++)
6083 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6084 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6085 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6086 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6087 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6088 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6089 VectorNormalize(normal);
6091 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 != 0);
6093 rsurface.svector3f = rsurface.array_deformedsvector3f;
6094 rsurface.svector3f_bufferobject = 0;
6095 rsurface.svector3f_bufferoffset = 0;
6096 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6097 rsurface.tvector3f_bufferobject = 0;
6098 rsurface.tvector3f_bufferoffset = 0;
6099 rsurface.normal3f = rsurface.array_deformednormal3f;
6100 rsurface.normal3f_bufferobject = 0;
6101 rsurface.normal3f_bufferoffset = 0;
6104 // deform vertex array to make wavey water and flags and such
6105 waveparms[0] = deform->waveparms[0];
6106 waveparms[1] = deform->waveparms[1];
6107 waveparms[2] = deform->waveparms[2];
6108 waveparms[3] = deform->waveparms[3];
6109 // this is how a divisor of vertex influence on deformation
6110 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6111 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6112 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6114 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6115 for (j = 0;j < surface->num_vertices;j++)
6117 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6118 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6119 // if the wavefunc depends on time, evaluate it per-vertex
6122 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6123 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6125 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6128 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6129 rsurface.vertex3f_bufferobject = 0;
6130 rsurface.vertex3f_bufferoffset = 0;
6132 case Q3DEFORM_BULGE:
6133 // deform vertex array to make the surface have moving bulges
6134 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6136 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6137 for (j = 0;j < surface->num_vertices;j++)
6139 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6140 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6143 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6144 rsurface.vertex3f_bufferobject = 0;
6145 rsurface.vertex3f_bufferoffset = 0;
6148 // deform vertex array
6149 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6150 VectorScale(deform->parms, scale, waveparms);
6151 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6153 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6154 for (j = 0;j < surface->num_vertices;j++)
6155 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6157 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6158 rsurface.vertex3f_bufferobject = 0;
6159 rsurface.vertex3f_bufferoffset = 0;
6163 // generate texcoords based on the chosen texcoord source
6164 switch(rsurface.texture->tcgen.tcgen)
6167 case Q3TCGEN_TEXTURE:
6168 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6169 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6170 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6172 case Q3TCGEN_LIGHTMAP:
6173 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6174 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6175 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6177 case Q3TCGEN_VECTOR:
6178 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6180 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6181 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)
6183 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6184 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6187 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6188 rsurface.texcoordtexture2f_bufferobject = 0;
6189 rsurface.texcoordtexture2f_bufferoffset = 0;
6191 case Q3TCGEN_ENVIRONMENT:
6192 // make environment reflections using a spheremap
6193 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6195 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6196 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6197 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6198 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6199 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6201 // identical to Q3A's method, but executed in worldspace so
6202 // carried models can be shiny too
6204 float viewer[3], d, reflected[3], worldreflected[3];
6206 VectorSubtract(rsurface.modelorg, vertex, viewer);
6207 // VectorNormalize(viewer);
6209 d = DotProduct(normal, viewer);
6211 reflected[0] = normal[0]*2*d - viewer[0];
6212 reflected[1] = normal[1]*2*d - viewer[1];
6213 reflected[2] = normal[2]*2*d - viewer[2];
6214 // note: this is proportinal to viewer, so we can normalize later
6216 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6217 VectorNormalize(worldreflected);
6219 // note: this sphere map only uses world x and z!
6220 // so positive and negative y will LOOK THE SAME.
6221 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6222 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6225 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6226 rsurface.texcoordtexture2f_bufferobject = 0;
6227 rsurface.texcoordtexture2f_bufferoffset = 0;
6230 // the only tcmod that needs software vertex processing is turbulent, so
6231 // check for it here and apply the changes if needed
6232 // and we only support that as the first one
6233 // (handling a mixture of turbulent and other tcmods would be problematic
6234 // without punting it entirely to a software path)
6235 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6237 amplitude = rsurface.texture->tcmods[0].parms[1];
6238 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6239 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6241 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6242 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)
6244 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6245 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6248 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6249 rsurface.texcoordtexture2f_bufferobject = 0;
6250 rsurface.texcoordtexture2f_bufferoffset = 0;
6252 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6253 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6254 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6255 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6258 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
6261 const msurface_t *surface = texturesurfacelist[0];
6262 const msurface_t *surface2;
6267 // TODO: lock all array ranges before render, rather than on each surface
6268 if (texturenumsurfaces == 1)
6270 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6271 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6273 else if (r_batchmode.integer == 2)
6275 #define MAXBATCHTRIANGLES 4096
6276 int batchtriangles = 0;
6277 int batchelements[MAXBATCHTRIANGLES*3];
6278 for (i = 0;i < texturenumsurfaces;i = j)
6280 surface = texturesurfacelist[i];
6282 if (surface->num_triangles > MAXBATCHTRIANGLES)
6284 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6287 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6288 batchtriangles = surface->num_triangles;
6289 firstvertex = surface->num_firstvertex;
6290 endvertex = surface->num_firstvertex + surface->num_vertices;
6291 for (;j < texturenumsurfaces;j++)
6293 surface2 = texturesurfacelist[j];
6294 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6296 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6297 batchtriangles += surface2->num_triangles;
6298 firstvertex = min(firstvertex, surface2->num_firstvertex);
6299 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6301 surface2 = texturesurfacelist[j-1];
6302 numvertices = endvertex - firstvertex;
6303 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6306 else if (r_batchmode.integer == 1)
6308 for (i = 0;i < texturenumsurfaces;i = j)
6310 surface = texturesurfacelist[i];
6311 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6312 if (texturesurfacelist[j] != surface2)
6314 surface2 = texturesurfacelist[j-1];
6315 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6316 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6317 GL_LockArrays(surface->num_firstvertex, numvertices);
6318 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6323 for (i = 0;i < texturenumsurfaces;i++)
6325 surface = texturesurfacelist[i];
6326 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6327 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6332 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6334 int i, planeindex, vertexindex;
6338 r_waterstate_waterplane_t *p, *bestp;
6339 msurface_t *surface;
6340 if (r_waterstate.renderingscene)
6342 for (i = 0;i < texturenumsurfaces;i++)
6344 surface = texturesurfacelist[i];
6345 if (lightmaptexunit >= 0)
6346 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6347 if (deluxemaptexunit >= 0)
6348 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6349 // pick the closest matching water plane
6352 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6355 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6357 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6358 d += fabs(PlaneDiff(vert, &p->plane));
6360 if (bestd > d || !bestp)
6368 if (refractiontexunit >= 0)
6369 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6370 if (reflectiontexunit >= 0)
6371 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6375 if (refractiontexunit >= 0)
6376 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6377 if (reflectiontexunit >= 0)
6378 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6380 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6381 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6385 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6389 const msurface_t *surface = texturesurfacelist[0];
6390 const msurface_t *surface2;
6395 // TODO: lock all array ranges before render, rather than on each surface
6396 if (texturenumsurfaces == 1)
6398 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6399 if (deluxemaptexunit >= 0)
6400 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6401 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6402 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6404 else if (r_batchmode.integer == 2)
6406 #define MAXBATCHTRIANGLES 4096
6407 int batchtriangles = 0;
6408 int batchelements[MAXBATCHTRIANGLES*3];
6409 for (i = 0;i < texturenumsurfaces;i = j)
6411 surface = texturesurfacelist[i];
6412 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6413 if (deluxemaptexunit >= 0)
6414 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6416 if (surface->num_triangles > MAXBATCHTRIANGLES)
6418 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6421 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6422 batchtriangles = surface->num_triangles;
6423 firstvertex = surface->num_firstvertex;
6424 endvertex = surface->num_firstvertex + surface->num_vertices;
6425 for (;j < texturenumsurfaces;j++)
6427 surface2 = texturesurfacelist[j];
6428 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6430 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6431 batchtriangles += surface2->num_triangles;
6432 firstvertex = min(firstvertex, surface2->num_firstvertex);
6433 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6435 surface2 = texturesurfacelist[j-1];
6436 numvertices = endvertex - firstvertex;
6437 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6440 else if (r_batchmode.integer == 1)
6443 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6444 for (i = 0;i < texturenumsurfaces;i = j)
6446 surface = texturesurfacelist[i];
6447 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6448 if (texturesurfacelist[j] != surface2)
6450 Con_Printf(" %i", j - i);
6453 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6455 for (i = 0;i < texturenumsurfaces;i = j)
6457 surface = texturesurfacelist[i];
6458 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6459 if (deluxemaptexunit >= 0)
6460 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6461 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6462 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6465 Con_Printf(" %i", j - i);
6467 surface2 = texturesurfacelist[j-1];
6468 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6469 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6470 GL_LockArrays(surface->num_firstvertex, numvertices);
6471 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6479 for (i = 0;i < texturenumsurfaces;i++)
6481 surface = texturesurfacelist[i];
6482 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6483 if (deluxemaptexunit >= 0)
6484 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6485 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6486 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6491 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6494 int texturesurfaceindex;
6495 if (r_showsurfaces.integer == 2)
6497 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6499 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6500 for (j = 0;j < surface->num_triangles;j++)
6502 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6503 GL_Color(f, f, f, 1);
6504 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6510 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6512 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6513 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6514 GL_Color((k & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1);
6515 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6516 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6521 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6523 int texturesurfaceindex;
6526 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6528 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6529 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)
6537 rsurface.lightmapcolor4f = rsurface.array_color4f;
6538 rsurface.lightmapcolor4f_bufferobject = 0;
6539 rsurface.lightmapcolor4f_bufferoffset = 0;
6542 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6544 int texturesurfaceindex;
6548 if (rsurface.lightmapcolor4f)
6550 // generate color arrays for the surfaces in this list
6551 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6553 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6554 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)
6556 f = FogPoint_Model(v);
6566 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6568 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6569 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)
6571 f = FogPoint_Model(v);
6579 rsurface.lightmapcolor4f = rsurface.array_color4f;
6580 rsurface.lightmapcolor4f_bufferobject = 0;
6581 rsurface.lightmapcolor4f_bufferoffset = 0;
6584 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6586 int texturesurfaceindex;
6590 if (!rsurface.lightmapcolor4f)
6592 // generate color arrays for the surfaces in this list
6593 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6595 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6596 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)
6598 f = FogPoint_Model(v);
6599 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6600 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6601 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6605 rsurface.lightmapcolor4f = rsurface.array_color4f;
6606 rsurface.lightmapcolor4f_bufferobject = 0;
6607 rsurface.lightmapcolor4f_bufferoffset = 0;
6610 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6612 int texturesurfaceindex;
6615 if (!rsurface.lightmapcolor4f)
6617 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6619 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6620 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)
6628 rsurface.lightmapcolor4f = rsurface.array_color4f;
6629 rsurface.lightmapcolor4f_bufferobject = 0;
6630 rsurface.lightmapcolor4f_bufferoffset = 0;
6633 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6635 int texturesurfaceindex;
6638 if (!rsurface.lightmapcolor4f)
6640 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6642 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6643 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)
6645 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6646 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6647 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6651 rsurface.lightmapcolor4f = rsurface.array_color4f;
6652 rsurface.lightmapcolor4f_bufferobject = 0;
6653 rsurface.lightmapcolor4f_bufferoffset = 0;
6656 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6659 rsurface.lightmapcolor4f = NULL;
6660 rsurface.lightmapcolor4f_bufferobject = 0;
6661 rsurface.lightmapcolor4f_bufferoffset = 0;
6662 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6663 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6664 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6665 GL_Color(r, g, b, a);
6666 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6669 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6671 // TODO: optimize applyfog && applycolor case
6672 // just apply fog if necessary, and tint the fog color array if necessary
6673 rsurface.lightmapcolor4f = NULL;
6674 rsurface.lightmapcolor4f_bufferobject = 0;
6675 rsurface.lightmapcolor4f_bufferoffset = 0;
6676 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6677 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6678 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6679 GL_Color(r, g, b, a);
6680 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6683 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6685 int texturesurfaceindex;
6689 if (texturesurfacelist[0]->lightmapinfo)
6691 // generate color arrays for the surfaces in this list
6692 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6694 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6695 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6697 if (surface->lightmapinfo->samples)
6699 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6700 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6701 VectorScale(lm, scale, c);
6702 if (surface->lightmapinfo->styles[1] != 255)
6704 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6706 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6707 VectorMA(c, scale, lm, c);
6708 if (surface->lightmapinfo->styles[2] != 255)
6711 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6712 VectorMA(c, scale, lm, c);
6713 if (surface->lightmapinfo->styles[3] != 255)
6716 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6717 VectorMA(c, scale, lm, c);
6727 rsurface.lightmapcolor4f = rsurface.array_color4f;
6728 rsurface.lightmapcolor4f_bufferobject = 0;
6729 rsurface.lightmapcolor4f_bufferoffset = 0;
6733 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6734 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6735 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6737 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6738 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6739 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6740 GL_Color(r, g, b, a);
6741 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6744 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6746 int texturesurfaceindex;
6749 float *v, *c, *c2, alpha;
6750 vec3_t ambientcolor;
6751 vec3_t diffusecolor;
6755 VectorCopy(rsurface.modellight_lightdir, lightdir);
6756 f = 0.5f * r_refdef.lightmapintensity;
6757 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6758 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6759 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6760 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6761 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6762 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6764 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6766 // generate color arrays for the surfaces in this list
6767 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6769 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6770 int numverts = surface->num_vertices;
6771 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6772 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6773 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6774 // q3-style directional shading
6775 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6777 if ((f = DotProduct(c2, lightdir)) > 0)
6778 VectorMA(ambientcolor, f, diffusecolor, c);
6780 VectorCopy(ambientcolor, c);
6788 rsurface.lightmapcolor4f = rsurface.array_color4f;
6789 rsurface.lightmapcolor4f_bufferobject = 0;
6790 rsurface.lightmapcolor4f_bufferoffset = 0;
6791 *applycolor = false;
6795 *r = ambientcolor[0];
6796 *g = ambientcolor[1];
6797 *b = ambientcolor[2];
6798 rsurface.lightmapcolor4f = NULL;
6799 rsurface.lightmapcolor4f_bufferobject = 0;
6800 rsurface.lightmapcolor4f_bufferoffset = 0;
6804 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6806 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6807 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6808 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6809 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6810 GL_Color(r, g, b, a);
6811 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6814 void RSurf_SetupDepthAndCulling(void)
6816 // submodels are biased to avoid z-fighting with world surfaces that they
6817 // may be exactly overlapping (avoids z-fighting artifacts on certain
6818 // doors and things in Quake maps)
6819 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6820 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6821 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6822 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6825 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6827 // transparent sky would be ridiculous
6828 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6830 R_SetupGenericShader(false);
6833 skyrendernow = false;
6834 // we have to force off the water clipping plane while rendering sky
6838 // restore entity matrix
6839 R_Mesh_Matrix(&rsurface.matrix);
6841 RSurf_SetupDepthAndCulling();
6843 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6844 // skymasking on them, and Quake3 never did sky masking (unlike
6845 // software Quake and software Quake2), so disable the sky masking
6846 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6847 // and skymasking also looks very bad when noclipping outside the
6848 // level, so don't use it then either.
6849 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6851 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6852 R_Mesh_ColorPointer(NULL, 0, 0);
6853 R_Mesh_ResetTextureState();
6854 if (skyrendermasked)
6856 R_SetupDepthOrShadowShader();
6857 // depth-only (masking)
6858 GL_ColorMask(0,0,0,0);
6859 // just to make sure that braindead drivers don't draw
6860 // anything despite that colormask...
6861 GL_BlendFunc(GL_ZERO, GL_ONE);
6865 R_SetupGenericShader(false);
6867 GL_BlendFunc(GL_ONE, GL_ZERO);
6869 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6870 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6871 if (skyrendermasked)
6872 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6874 R_Mesh_ResetTextureState();
6875 GL_Color(1, 1, 1, 1);
6878 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6880 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6883 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6884 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6885 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6886 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6887 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6888 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6889 if (rsurface.texture->backgroundcurrentskinframe)
6891 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6892 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6893 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6894 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6896 if(rsurface.texture->colormapping)
6898 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6899 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6901 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6902 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6903 R_Mesh_ColorPointer(NULL, 0, 0);
6905 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6907 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6909 // render background
6910 GL_BlendFunc(GL_ONE, GL_ZERO);
6912 GL_AlphaTest(false);
6914 GL_Color(1, 1, 1, 1);
6915 R_Mesh_ColorPointer(NULL, 0, 0);
6917 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6918 if (r_glsl_permutation)
6920 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6921 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6922 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6923 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6924 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6925 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6926 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
6928 GL_LockArrays(0, 0);
6930 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6931 GL_DepthMask(false);
6932 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6933 R_Mesh_ColorPointer(NULL, 0, 0);
6935 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6936 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6937 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6940 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6941 if (!r_glsl_permutation)
6944 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6945 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6946 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6947 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6948 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6949 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6951 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6953 GL_BlendFunc(GL_ONE, GL_ZERO);
6955 GL_AlphaTest(false);
6959 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6960 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6961 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6964 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6966 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6967 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
6969 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6973 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6974 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
6976 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6978 GL_LockArrays(0, 0);
6981 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6983 // OpenGL 1.3 path - anything not completely ancient
6984 int texturesurfaceindex;
6985 qboolean applycolor;
6989 const texturelayer_t *layer;
6990 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6992 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6995 int layertexrgbscale;
6996 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6998 if (layerindex == 0)
7002 GL_AlphaTest(false);
7003 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7006 GL_DepthMask(layer->depthmask && writedepth);
7007 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7008 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7010 layertexrgbscale = 4;
7011 VectorScale(layer->color, 0.25f, layercolor);
7013 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7015 layertexrgbscale = 2;
7016 VectorScale(layer->color, 0.5f, layercolor);
7020 layertexrgbscale = 1;
7021 VectorScale(layer->color, 1.0f, layercolor);
7023 layercolor[3] = layer->color[3];
7024 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7025 R_Mesh_ColorPointer(NULL, 0, 0);
7026 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7027 switch (layer->type)
7029 case TEXTURELAYERTYPE_LITTEXTURE:
7030 memset(&m, 0, sizeof(m));
7031 m.tex[0] = R_GetTexture(r_texture_white);
7032 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7033 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7034 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7035 m.tex[1] = R_GetTexture(layer->texture);
7036 m.texmatrix[1] = layer->texmatrix;
7037 m.texrgbscale[1] = layertexrgbscale;
7038 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7039 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7040 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7041 R_Mesh_TextureState(&m);
7042 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7043 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7044 else if (rsurface.uselightmaptexture)
7045 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7047 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7049 case TEXTURELAYERTYPE_TEXTURE:
7050 memset(&m, 0, sizeof(m));
7051 m.tex[0] = R_GetTexture(layer->texture);
7052 m.texmatrix[0] = layer->texmatrix;
7053 m.texrgbscale[0] = layertexrgbscale;
7054 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7055 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7056 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7057 R_Mesh_TextureState(&m);
7058 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7060 case TEXTURELAYERTYPE_FOG:
7061 memset(&m, 0, sizeof(m));
7062 m.texrgbscale[0] = layertexrgbscale;
7065 m.tex[0] = R_GetTexture(layer->texture);
7066 m.texmatrix[0] = layer->texmatrix;
7067 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7068 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7069 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7071 R_Mesh_TextureState(&m);
7072 // generate a color array for the fog pass
7073 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7074 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7078 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7079 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)
7081 f = 1 - FogPoint_Model(v);
7082 c[0] = layercolor[0];
7083 c[1] = layercolor[1];
7084 c[2] = layercolor[2];
7085 c[3] = f * layercolor[3];
7088 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7091 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7093 GL_LockArrays(0, 0);
7096 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7098 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7099 GL_AlphaTest(false);
7103 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7105 // OpenGL 1.1 - crusty old voodoo path
7106 int texturesurfaceindex;
7110 const texturelayer_t *layer;
7111 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7113 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7115 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7117 if (layerindex == 0)
7121 GL_AlphaTest(false);
7122 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7125 GL_DepthMask(layer->depthmask && writedepth);
7126 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7127 R_Mesh_ColorPointer(NULL, 0, 0);
7128 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7129 switch (layer->type)
7131 case TEXTURELAYERTYPE_LITTEXTURE:
7132 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7134 // two-pass lit texture with 2x rgbscale
7135 // first the lightmap pass
7136 memset(&m, 0, sizeof(m));
7137 m.tex[0] = R_GetTexture(r_texture_white);
7138 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7139 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7140 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7141 R_Mesh_TextureState(&m);
7142 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7143 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7144 else if (rsurface.uselightmaptexture)
7145 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7147 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7148 GL_LockArrays(0, 0);
7149 // then apply the texture to it
7150 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7151 memset(&m, 0, sizeof(m));
7152 m.tex[0] = R_GetTexture(layer->texture);
7153 m.texmatrix[0] = layer->texmatrix;
7154 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7155 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7156 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7157 R_Mesh_TextureState(&m);
7158 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);
7162 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7163 memset(&m, 0, sizeof(m));
7164 m.tex[0] = R_GetTexture(layer->texture);
7165 m.texmatrix[0] = layer->texmatrix;
7166 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7167 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7168 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7169 R_Mesh_TextureState(&m);
7170 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7171 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);
7173 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);
7176 case TEXTURELAYERTYPE_TEXTURE:
7177 // singletexture unlit texture with transparency support
7178 memset(&m, 0, sizeof(m));
7179 m.tex[0] = R_GetTexture(layer->texture);
7180 m.texmatrix[0] = layer->texmatrix;
7181 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7182 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7183 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7184 R_Mesh_TextureState(&m);
7185 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);
7187 case TEXTURELAYERTYPE_FOG:
7188 // singletexture fogging
7189 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7192 memset(&m, 0, sizeof(m));
7193 m.tex[0] = R_GetTexture(layer->texture);
7194 m.texmatrix[0] = layer->texmatrix;
7195 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7196 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7197 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7198 R_Mesh_TextureState(&m);
7201 R_Mesh_ResetTextureState();
7202 // generate a color array for the fog pass
7203 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7207 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7208 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)
7210 f = 1 - FogPoint_Model(v);
7211 c[0] = layer->color[0];
7212 c[1] = layer->color[1];
7213 c[2] = layer->color[2];
7214 c[3] = f * layer->color[3];
7217 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7220 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7222 GL_LockArrays(0, 0);
7225 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7227 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7228 GL_AlphaTest(false);
7232 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7236 GL_AlphaTest(false);
7237 R_Mesh_ColorPointer(NULL, 0, 0);
7238 R_Mesh_ResetTextureState();
7239 R_SetupGenericShader(false);
7241 if(rsurface.texture && rsurface.texture->currentskinframe)
7243 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7244 c[3] *= rsurface.texture->currentalpha;
7254 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7256 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7257 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7258 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7261 // brighten it up (as texture value 127 means "unlit")
7262 c[0] *= 2 * r_refdef.view.colorscale;
7263 c[1] *= 2 * r_refdef.view.colorscale;
7264 c[2] *= 2 * r_refdef.view.colorscale;
7266 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7267 c[3] *= r_wateralpha.value;
7269 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7271 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7272 GL_DepthMask(false);
7274 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7276 GL_BlendFunc(GL_ONE, GL_ONE);
7277 GL_DepthMask(false);
7279 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7281 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7282 GL_DepthMask(false);
7284 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7286 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7287 GL_DepthMask(false);
7291 GL_BlendFunc(GL_ONE, GL_ZERO);
7292 GL_DepthMask(writedepth);
7295 rsurface.lightmapcolor4f = NULL;
7297 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7299 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7301 rsurface.lightmapcolor4f = NULL;
7302 rsurface.lightmapcolor4f_bufferobject = 0;
7303 rsurface.lightmapcolor4f_bufferoffset = 0;
7305 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7307 qboolean applycolor = true;
7310 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7312 r_refdef.lightmapintensity = 1;
7313 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7314 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7318 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7320 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7321 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7322 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7325 if(!rsurface.lightmapcolor4f)
7326 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7328 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7329 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7330 if(r_refdef.fogenabled)
7331 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7333 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7334 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7337 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7340 RSurf_SetupDepthAndCulling();
7341 if (r_showsurfaces.integer == 3)
7342 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7343 else if (r_glsl.integer && gl_support_fragment_shader)
7344 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7345 else if (gl_combine.integer && r_textureunits.integer >= 2)
7346 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7348 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7352 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7355 RSurf_SetupDepthAndCulling();
7356 if (r_showsurfaces.integer == 3)
7357 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7358 else if (r_glsl.integer && gl_support_fragment_shader)
7359 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7360 else if (gl_combine.integer && r_textureunits.integer >= 2)
7361 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7363 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7367 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7370 int texturenumsurfaces, endsurface;
7372 msurface_t *surface;
7373 msurface_t *texturesurfacelist[1024];
7375 // if the model is static it doesn't matter what value we give for
7376 // wantnormals and wanttangents, so this logic uses only rules applicable
7377 // to a model, knowing that they are meaningless otherwise
7378 if (ent == r_refdef.scene.worldentity)
7379 RSurf_ActiveWorldEntity();
7380 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7381 RSurf_ActiveModelEntity(ent, false, false);
7383 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7385 for (i = 0;i < numsurfaces;i = j)
7388 surface = rsurface.modelsurfaces + surfacelist[i];
7389 texture = surface->texture;
7390 rsurface.texture = R_GetCurrentTexture(texture);
7391 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7392 // scan ahead until we find a different texture
7393 endsurface = min(i + 1024, numsurfaces);
7394 texturenumsurfaces = 0;
7395 texturesurfacelist[texturenumsurfaces++] = surface;
7396 for (;j < endsurface;j++)
7398 surface = rsurface.modelsurfaces + surfacelist[j];
7399 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7401 texturesurfacelist[texturenumsurfaces++] = surface;
7403 // render the range of surfaces
7404 if (ent == r_refdef.scene.worldentity)
7405 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7407 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7409 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7410 GL_AlphaTest(false);
7413 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7415 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7419 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7421 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7423 RSurf_SetupDepthAndCulling();
7424 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7425 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7427 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7429 RSurf_SetupDepthAndCulling();
7430 GL_AlphaTest(false);
7431 R_Mesh_ColorPointer(NULL, 0, 0);
7432 R_Mesh_ResetTextureState();
7433 R_SetupGenericShader(false);
7434 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7436 GL_BlendFunc(GL_ONE, GL_ZERO);
7437 GL_Color(0, 0, 0, 1);
7438 GL_DepthTest(writedepth);
7439 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7441 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7443 RSurf_SetupDepthAndCulling();
7444 GL_AlphaTest(false);
7445 R_Mesh_ColorPointer(NULL, 0, 0);
7446 R_Mesh_ResetTextureState();
7447 R_SetupGenericShader(false);
7448 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7450 GL_BlendFunc(GL_ONE, GL_ZERO);
7452 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7454 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7455 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7456 else if (!rsurface.texture->currentnumlayers)
7458 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7460 // transparent surfaces get pushed off into the transparent queue
7461 int surfacelistindex;
7462 const msurface_t *surface;
7463 vec3_t tempcenter, center;
7464 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7466 surface = texturesurfacelist[surfacelistindex];
7467 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7468 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7469 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7470 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7471 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7476 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7477 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7482 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7486 // break the surface list down into batches by texture and use of lightmapping
7487 for (i = 0;i < numsurfaces;i = j)
7490 // texture is the base texture pointer, rsurface.texture is the
7491 // current frame/skin the texture is directing us to use (for example
7492 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7493 // use skin 1 instead)
7494 texture = surfacelist[i]->texture;
7495 rsurface.texture = R_GetCurrentTexture(texture);
7496 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7497 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7499 // if this texture is not the kind we want, skip ahead to the next one
7500 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7504 // simply scan ahead until we find a different texture or lightmap state
7505 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7507 // render the range of surfaces
7508 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7512 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7517 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7519 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7521 RSurf_SetupDepthAndCulling();
7522 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7523 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7525 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7527 RSurf_SetupDepthAndCulling();
7528 GL_AlphaTest(false);
7529 R_Mesh_ColorPointer(NULL, 0, 0);
7530 R_Mesh_ResetTextureState();
7531 R_SetupGenericShader(false);
7532 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7534 GL_BlendFunc(GL_ONE, GL_ZERO);
7535 GL_Color(0, 0, 0, 1);
7536 GL_DepthTest(writedepth);
7537 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7539 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7541 RSurf_SetupDepthAndCulling();
7542 GL_AlphaTest(false);
7543 R_Mesh_ColorPointer(NULL, 0, 0);
7544 R_Mesh_ResetTextureState();
7545 R_SetupGenericShader(false);
7546 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7548 GL_BlendFunc(GL_ONE, GL_ZERO);
7550 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7552 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7553 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7554 else if (!rsurface.texture->currentnumlayers)
7556 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7558 // transparent surfaces get pushed off into the transparent queue
7559 int surfacelistindex;
7560 const msurface_t *surface;
7561 vec3_t tempcenter, center;
7562 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7564 surface = texturesurfacelist[surfacelistindex];
7565 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7566 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7567 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7568 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7569 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7574 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7575 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7580 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7584 // break the surface list down into batches by texture and use of lightmapping
7585 for (i = 0;i < numsurfaces;i = j)
7588 // texture is the base texture pointer, rsurface.texture is the
7589 // current frame/skin the texture is directing us to use (for example
7590 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7591 // use skin 1 instead)
7592 texture = surfacelist[i]->texture;
7593 rsurface.texture = R_GetCurrentTexture(texture);
7594 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7595 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7597 // if this texture is not the kind we want, skip ahead to the next one
7598 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7602 // simply scan ahead until we find a different texture or lightmap state
7603 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7605 // render the range of surfaces
7606 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7610 float locboxvertex3f[6*4*3] =
7612 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7613 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7614 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7615 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7616 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7617 1,0,0, 0,0,0, 0,1,0, 1,1,0
7620 unsigned short locboxelements[6*2*3] =
7630 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7633 cl_locnode_t *loc = (cl_locnode_t *)ent;
7635 float vertex3f[6*4*3];
7637 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7638 GL_DepthMask(false);
7639 GL_DepthRange(0, 1);
7640 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7642 GL_CullFace(GL_NONE);
7643 R_Mesh_Matrix(&identitymatrix);
7645 R_Mesh_VertexPointer(vertex3f, 0, 0);
7646 R_Mesh_ColorPointer(NULL, 0, 0);
7647 R_Mesh_ResetTextureState();
7648 R_SetupGenericShader(false);
7651 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7652 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7653 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7654 surfacelist[0] < 0 ? 0.5f : 0.125f);
7656 if (VectorCompare(loc->mins, loc->maxs))
7658 VectorSet(size, 2, 2, 2);
7659 VectorMA(loc->mins, -0.5f, size, mins);
7663 VectorCopy(loc->mins, mins);
7664 VectorSubtract(loc->maxs, loc->mins, size);
7667 for (i = 0;i < 6*4*3;)
7668 for (j = 0;j < 3;j++, i++)
7669 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7671 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7674 void R_DrawLocs(void)
7677 cl_locnode_t *loc, *nearestloc;
7679 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7680 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7682 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7683 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7687 void R_DrawDebugModel(entity_render_t *ent)
7689 int i, j, k, l, flagsmask;
7690 const int *elements;
7692 msurface_t *surface;
7693 dp_model_t *model = ent->model;
7696 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7698 R_Mesh_ColorPointer(NULL, 0, 0);
7699 R_Mesh_ResetTextureState();
7700 R_SetupGenericShader(false);
7701 GL_DepthRange(0, 1);
7702 GL_DepthTest(!r_showdisabledepthtest.integer);
7703 GL_DepthMask(false);
7704 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7706 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7708 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7709 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7711 if (brush->colbrushf && brush->colbrushf->numtriangles)
7713 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7714 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
7715 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7718 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7720 if (surface->num_collisiontriangles)
7722 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7723 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
7724 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7729 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7731 if (r_showtris.integer || r_shownormals.integer)
7733 if (r_showdisabledepthtest.integer)
7735 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7736 GL_DepthMask(false);
7740 GL_BlendFunc(GL_ONE, GL_ZERO);
7743 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7745 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7747 rsurface.texture = R_GetCurrentTexture(surface->texture);
7748 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7750 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7751 if (r_showtris.value > 0)
7753 if (!rsurface.texture->currentlayers->depthmask)
7754 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7755 else if (ent == r_refdef.scene.worldentity)
7756 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7758 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7759 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7760 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7761 R_Mesh_ColorPointer(NULL, 0, 0);
7762 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7763 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7764 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7765 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7766 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7769 if (r_shownormals.value < 0)
7772 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7774 VectorCopy(rsurface.vertex3f + l * 3, v);
7775 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7776 qglVertex3f(v[0], v[1], v[2]);
7777 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7778 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7779 qglVertex3f(v[0], v[1], v[2]);
7784 if (r_shownormals.value > 0)
7787 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7789 VectorCopy(rsurface.vertex3f + l * 3, v);
7790 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7791 qglVertex3f(v[0], v[1], v[2]);
7792 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7793 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7794 qglVertex3f(v[0], v[1], v[2]);
7799 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7801 VectorCopy(rsurface.vertex3f + l * 3, v);
7802 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7803 qglVertex3f(v[0], v[1], v[2]);
7804 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7805 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7806 qglVertex3f(v[0], v[1], v[2]);
7811 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7813 VectorCopy(rsurface.vertex3f + l * 3, v);
7814 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7815 qglVertex3f(v[0], v[1], v[2]);
7816 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7817 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7818 qglVertex3f(v[0], v[1], v[2]);
7825 rsurface.texture = NULL;
7829 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7830 int r_maxsurfacelist = 0;
7831 msurface_t **r_surfacelist = NULL;
7832 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7834 int i, j, endj, f, flagsmask;
7836 dp_model_t *model = r_refdef.scene.worldmodel;
7837 msurface_t *surfaces;
7838 unsigned char *update;
7839 int numsurfacelist = 0;
7843 if (r_maxsurfacelist < model->num_surfaces)
7845 r_maxsurfacelist = model->num_surfaces;
7847 Mem_Free(r_surfacelist);
7848 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7851 RSurf_ActiveWorldEntity();
7853 surfaces = model->data_surfaces;
7854 update = model->brushq1.lightmapupdateflags;
7856 // update light styles on this submodel
7857 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7859 model_brush_lightstyleinfo_t *style;
7860 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7862 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7864 int *list = style->surfacelist;
7865 style->value = r_refdef.scene.lightstylevalue[style->style];
7866 for (j = 0;j < style->numsurfaces;j++)
7867 update[list[j]] = true;
7872 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7876 R_DrawDebugModel(r_refdef.scene.worldentity);
7877 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7883 rsurface.uselightmaptexture = false;
7884 rsurface.texture = NULL;
7885 rsurface.rtlight = NULL;
7887 // add visible surfaces to draw list
7888 for (i = 0;i < model->nummodelsurfaces;i++)
7890 j = model->sortedmodelsurfaces[i];
7891 if (r_refdef.viewcache.world_surfacevisible[j])
7892 r_surfacelist[numsurfacelist++] = surfaces + j;
7894 // update lightmaps if needed
7896 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7897 if (r_refdef.viewcache.world_surfacevisible[j])
7899 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7900 // don't do anything if there were no surfaces
7901 if (!numsurfacelist)
7903 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7906 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7907 GL_AlphaTest(false);
7909 // add to stats if desired
7910 if (r_speeds.integer && !skysurfaces && !depthonly)
7912 r_refdef.stats.world_surfaces += numsurfacelist;
7913 for (j = 0;j < numsurfacelist;j++)
7914 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7916 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7919 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7921 int i, j, endj, f, flagsmask;
7923 dp_model_t *model = ent->model;
7924 msurface_t *surfaces;
7925 unsigned char *update;
7926 int numsurfacelist = 0;
7930 if (r_maxsurfacelist < model->num_surfaces)
7932 r_maxsurfacelist = model->num_surfaces;
7934 Mem_Free(r_surfacelist);
7935 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7938 // if the model is static it doesn't matter what value we give for
7939 // wantnormals and wanttangents, so this logic uses only rules applicable
7940 // to a model, knowing that they are meaningless otherwise
7941 if (ent == r_refdef.scene.worldentity)
7942 RSurf_ActiveWorldEntity();
7943 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7944 RSurf_ActiveModelEntity(ent, false, false);
7946 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7948 surfaces = model->data_surfaces;
7949 update = model->brushq1.lightmapupdateflags;
7951 // update light styles
7952 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7954 model_brush_lightstyleinfo_t *style;
7955 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7957 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7959 int *list = style->surfacelist;
7960 style->value = r_refdef.scene.lightstylevalue[style->style];
7961 for (j = 0;j < style->numsurfaces;j++)
7962 update[list[j]] = true;
7967 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7971 R_DrawDebugModel(ent);
7972 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7978 rsurface.uselightmaptexture = false;
7979 rsurface.texture = NULL;
7980 rsurface.rtlight = NULL;
7982 // add visible surfaces to draw list
7983 for (i = 0;i < model->nummodelsurfaces;i++)
7984 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7985 // don't do anything if there were no surfaces
7986 if (!numsurfacelist)
7988 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7991 // update lightmaps if needed
7993 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7995 R_BuildLightMap(ent, surfaces + j);
7996 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7997 GL_AlphaTest(false);
7999 // add to stats if desired
8000 if (r_speeds.integer && !skysurfaces && !depthonly)
8002 r_refdef.stats.entities_surfaces += numsurfacelist;
8003 for (j = 0;j < numsurfacelist;j++)
8004 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8006 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity