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", "4", "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"
464 "# ifdef GL_AMD_texture_texture4\n"
465 "# extension GL_AMD_texture_texture4 : enable\n"
470 "#ifdef USESHADOWMAPCUBE\n"
471 "# extension GL_EXT_gpu_shader4 : enable\n"
474 "#ifdef USESHADOWSAMPLER\n"
475 "# extension GL_ARB_shadow : enable\n"
478 "// common definitions between vertex shader and fragment shader:\n"
480 "//#ifdef __GLSL_CG_DATA_TYPES\n"
481 "//# define myhalf half\n"
482 "//# define myhalf2 half2\n"
483 "//# define myhalf3half3\n"
484 "//# define myhalf4 half4\n"
486 "# define myhalf float\n"
487 "# define myhalf2 vec2\n"
488 "# define myhalf3 vec3\n"
489 "# define myhalf4 vec4\n"
492 "#ifdef MODE_DEPTH_OR_SHADOW\n"
494 "# ifdef VERTEX_SHADER\n"
497 " gl_Position = ftransform();\n"
502 "#ifdef MODE_SHOWDEPTH\n"
503 "# ifdef VERTEX_SHADER\n"
506 " gl_Position = ftransform();\n"
507 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
510 "# ifdef FRAGMENT_SHADER\n"
513 " gl_FragColor = gl_Color;\n"
517 "#else // !MODE_SHOWDEPTH\n"
519 "#ifdef MODE_POSTPROCESS\n"
520 "# ifdef VERTEX_SHADER\n"
523 " gl_FrontColor = gl_Color;\n"
524 " gl_Position = ftransform();\n"
525 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
527 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
531 "# ifdef FRAGMENT_SHADER\n"
533 "uniform sampler2D Texture_First;\n"
535 "uniform sampler2D Texture_Second;\n"
537 "#ifdef USEGAMMARAMPS\n"
538 "uniform sampler2D Texture_GammaRamps;\n"
540 "#ifdef USESATURATION\n"
541 "uniform float Saturation;\n"
543 "#ifdef USEVIEWTINT\n"
544 "uniform vec4 TintColor;\n"
546 "//uncomment these if you want to use them:\n"
547 "uniform vec4 UserVec1;\n"
548 "// uniform vec4 UserVec2;\n"
549 "// uniform vec4 UserVec3;\n"
550 "// uniform vec4 UserVec4;\n"
551 "// uniform float ClientTime;\n"
552 "uniform vec2 PixelSize;\n"
555 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
557 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
559 "#ifdef USEVIEWTINT\n"
560 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
563 "#ifdef USEPOSTPROCESSING\n"
564 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
565 "// 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"
566 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
567 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
568 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
569 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
570 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
571 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
574 "#ifdef USESATURATION\n"
575 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
576 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
577 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
578 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
581 "#ifdef USEGAMMARAMPS\n"
582 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
583 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
584 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
591 "#ifdef MODE_GENERIC\n"
592 "# ifdef VERTEX_SHADER\n"
595 " gl_FrontColor = gl_Color;\n"
596 "# ifdef USEDIFFUSE\n"
597 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
599 "# ifdef USESPECULAR\n"
600 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
602 " gl_Position = ftransform();\n"
605 "# ifdef FRAGMENT_SHADER\n"
607 "# ifdef USEDIFFUSE\n"
608 "uniform sampler2D Texture_First;\n"
610 "# ifdef USESPECULAR\n"
611 "uniform sampler2D Texture_Second;\n"
616 " gl_FragColor = gl_Color;\n"
617 "# ifdef USEDIFFUSE\n"
618 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
621 "# ifdef USESPECULAR\n"
622 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
624 "# ifdef USECOLORMAPPING\n"
625 " gl_FragColor *= tex2;\n"
628 " gl_FragColor += tex2;\n"
630 "# ifdef USEVERTEXTEXTUREBLEND\n"
631 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
636 "#else // !MODE_GENERIC\n"
638 "varying vec2 TexCoord;\n"
639 "#ifdef USEVERTEXTEXTUREBLEND\n"
640 "varying vec2 TexCoord2;\n"
642 "varying vec2 TexCoordLightmap;\n"
644 "#ifdef MODE_LIGHTSOURCE\n"
645 "varying vec3 CubeVector;\n"
648 "#ifdef MODE_LIGHTSOURCE\n"
649 "varying vec3 LightVector;\n"
651 "#ifdef MODE_LIGHTDIRECTION\n"
652 "varying vec3 LightVector;\n"
655 "varying vec3 EyeVector;\n"
657 "varying vec3 EyeVectorModelSpace;\n"
660 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
661 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
662 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
664 "#ifdef MODE_WATER\n"
665 "varying vec4 ModelViewProjectionPosition;\n"
667 "#ifdef MODE_REFRACTION\n"
668 "varying vec4 ModelViewProjectionPosition;\n"
670 "#ifdef USEREFLECTION\n"
671 "varying vec4 ModelViewProjectionPosition;\n"
678 "// vertex shader specific:\n"
679 "#ifdef VERTEX_SHADER\n"
681 "uniform vec3 LightPosition;\n"
682 "uniform vec3 EyePosition;\n"
683 "uniform vec3 LightDir;\n"
685 "// 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"
689 " gl_FrontColor = gl_Color;\n"
690 " // copy the surface texcoord\n"
691 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
692 "#ifdef USEVERTEXTEXTUREBLEND\n"
693 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
695 "#ifndef MODE_LIGHTSOURCE\n"
696 "# ifndef MODE_LIGHTDIRECTION\n"
697 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
701 "#ifdef MODE_LIGHTSOURCE\n"
702 " // transform vertex position into light attenuation/cubemap space\n"
703 " // (-1 to +1 across the light box)\n"
704 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
706 " // transform unnormalized light direction into tangent space\n"
707 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
708 " // normalize it per pixel)\n"
709 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
710 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
711 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
712 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
715 "#ifdef MODE_LIGHTDIRECTION\n"
716 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
717 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
718 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
721 " // transform unnormalized eye direction into tangent space\n"
723 " vec3 EyeVectorModelSpace;\n"
725 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
726 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
727 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
728 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
730 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
731 " VectorS = gl_MultiTexCoord1.xyz;\n"
732 " VectorT = gl_MultiTexCoord2.xyz;\n"
733 " VectorR = gl_MultiTexCoord3.xyz;\n"
736 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
737 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
738 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
739 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
742 "// transform vertex to camera space, using ftransform to match non-VS\n"
744 " gl_Position = ftransform();\n"
746 "#ifdef MODE_WATER\n"
747 " ModelViewProjectionPosition = gl_Position;\n"
749 "#ifdef MODE_REFRACTION\n"
750 " ModelViewProjectionPosition = gl_Position;\n"
752 "#ifdef USEREFLECTION\n"
753 " ModelViewProjectionPosition = gl_Position;\n"
757 "#endif // VERTEX_SHADER\n"
762 "// fragment shader specific:\n"
763 "#ifdef FRAGMENT_SHADER\n"
765 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
766 "uniform sampler2D Texture_Normal;\n"
767 "uniform sampler2D Texture_Color;\n"
768 "uniform sampler2D Texture_Gloss;\n"
769 "uniform sampler2D Texture_Glow;\n"
770 "uniform sampler2D Texture_SecondaryNormal;\n"
771 "uniform sampler2D Texture_SecondaryColor;\n"
772 "uniform sampler2D Texture_SecondaryGloss;\n"
773 "uniform sampler2D Texture_SecondaryGlow;\n"
774 "uniform sampler2D Texture_Pants;\n"
775 "uniform sampler2D Texture_Shirt;\n"
776 "uniform sampler2D Texture_FogMask;\n"
777 "uniform sampler2D Texture_Lightmap;\n"
778 "uniform sampler2D Texture_Deluxemap;\n"
779 "uniform sampler2D Texture_Refraction;\n"
780 "uniform sampler2D Texture_Reflection;\n"
781 "uniform sampler2D Texture_Attenuation;\n"
782 "uniform samplerCube Texture_Cube;\n"
784 "#define showshadowmap 0\n"
786 "#ifdef USESHADOWMAPRECT\n"
787 "# ifdef USESHADOWSAMPLER\n"
788 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
790 "uniform sampler2DRect Texture_ShadowMapRect;\n"
794 "#ifdef USESHADOWMAP2D\n"
795 "# ifdef USESHADOWSAMPLER\n"
796 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
798 "uniform sampler2D Texture_ShadowMap2D;\n"
802 "#ifdef USESHADOWMAPVSDCT\n"
803 "uniform samplerCube Texture_CubeProjection;\n"
806 "#ifdef USESHADOWMAPCUBE\n"
807 "# ifdef USESHADOWSAMPLER\n"
808 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
810 "uniform samplerCube Texture_ShadowMapCube;\n"
814 "uniform myhalf3 LightColor;\n"
815 "uniform myhalf3 AmbientColor;\n"
816 "uniform myhalf3 DiffuseColor;\n"
817 "uniform myhalf3 SpecularColor;\n"
818 "uniform myhalf3 Color_Pants;\n"
819 "uniform myhalf3 Color_Shirt;\n"
820 "uniform myhalf3 FogColor;\n"
822 "uniform myhalf4 TintColor;\n"
825 "//#ifdef MODE_WATER\n"
826 "uniform vec4 DistortScaleRefractReflect;\n"
827 "uniform vec4 ScreenScaleRefractReflect;\n"
828 "uniform vec4 ScreenCenterRefractReflect;\n"
829 "uniform myhalf4 RefractColor;\n"
830 "uniform myhalf4 ReflectColor;\n"
831 "uniform myhalf ReflectFactor;\n"
832 "uniform myhalf ReflectOffset;\n"
834 "//# ifdef MODE_REFRACTION\n"
835 "//uniform vec4 DistortScaleRefractReflect;\n"
836 "//uniform vec4 ScreenScaleRefractReflect;\n"
837 "//uniform vec4 ScreenCenterRefractReflect;\n"
838 "//uniform myhalf4 RefractColor;\n"
839 "//# ifdef USEREFLECTION\n"
840 "//uniform myhalf4 ReflectColor;\n"
843 "//# ifdef USEREFLECTION\n"
844 "//uniform vec4 DistortScaleRefractReflect;\n"
845 "//uniform vec4 ScreenScaleRefractReflect;\n"
846 "//uniform vec4 ScreenCenterRefractReflect;\n"
847 "//uniform myhalf4 ReflectColor;\n"
852 "uniform myhalf3 GlowColor;\n"
853 "uniform myhalf SceneBrightness;\n"
855 "uniform float OffsetMapping_Scale;\n"
856 "uniform float OffsetMapping_Bias;\n"
857 "uniform float FogRangeRecip;\n"
859 "uniform myhalf AmbientScale;\n"
860 "uniform myhalf DiffuseScale;\n"
861 "uniform myhalf SpecularScale;\n"
862 "uniform myhalf SpecularPower;\n"
864 "#ifdef USEOFFSETMAPPING\n"
865 "vec2 OffsetMapping(vec2 TexCoord)\n"
867 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
868 " // 14 sample relief mapping: linear search and then binary search\n"
869 " // this basically steps forward a small amount repeatedly until it finds\n"
870 " // itself inside solid, then jitters forward and back using decreasing\n"
871 " // amounts to find the impact\n"
872 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
873 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
874 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
875 " vec3 RT = vec3(TexCoord, 1);\n"
876 " OffsetVector *= 0.1;\n"
877 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
878 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
879 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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) - 0.5);\n"
887 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
888 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
889 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
890 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
893 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
894 " // this basically moves forward the full distance, and then backs up based\n"
895 " // on height of samples\n"
896 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
897 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
898 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
899 " TexCoord += OffsetVector;\n"
900 " OffsetVector *= 0.333;\n"
901 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
902 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
903 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
904 " return TexCoord;\n"
907 "#endif // USEOFFSETMAPPING\n"
909 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
910 "uniform vec2 ShadowMap_TextureScale;\n"
911 "uniform vec4 ShadowMap_Parameters;\n"
914 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
915 "vec3 GetShadowMapTC2D(vec3 dir)\n"
917 " vec3 adir = abs(dir);\n"
918 "# ifndef USESHADOWMAPVSDCT\n"
922 " if (adir.x > adir.y)\n"
924 " if (adir.x > adir.z) // X\n"
928 " offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
934 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
939 " if (adir.y > adir.z) // Y\n"
943 " offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
949 " offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
953 " vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
954 " stc.xy += offset * ShadowMap_Parameters.y;\n"
955 " stc.z += ShadowMap_Parameters.z;\n"
956 "# if showshadowmap\n"
957 " stc.xy *= ShadowMap_TextureScale;\n"
961 " vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
962 " float ma = max(max(adir.x, adir.y), adir.z);\n"
963 " vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
964 " stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
965 " stc.z += ShadowMap_Parameters.z;\n"
966 "# if showshadowmap\n"
967 " stc.xy *= ShadowMap_TextureScale;\n"
972 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
974 "#ifdef USESHADOWMAPCUBE\n"
975 "vec4 GetShadowMapTCCube(vec3 dir)\n"
977 " vec3 adir = abs(dir);\n"
978 " return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
982 "#if !showshadowmap\n"
983 "# ifdef USESHADOWMAPRECT\n"
984 "float ShadowMapCompare(vec3 dir)\n"
986 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
988 "# ifdef USESHADOWSAMPLER\n"
990 "# ifdef USESHADOWMAPPCF\n"
991 "# define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
992 " 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"
994 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
999 "# ifdef USESHADOWMAPPCF\n"
1000 "# if USESHADOWMAPPCF > 1\n"
1001 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1002 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1003 " 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"
1004 " vec4 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"
1005 " vec4 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"
1006 " vec4 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"
1007 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1008 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1010 "# define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1011 " vec2 offset = fract(shadowmaptc.xy);\n"
1012 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1013 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1014 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1015 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1016 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1019 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1027 "# ifdef USESHADOWMAP2D\n"
1028 "float ShadowMapCompare(vec3 dir)\n"
1030 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1033 "# ifdef USESHADOWSAMPLER\n"
1034 "# ifdef USESHADOWMAPPCF\n"
1035 "# define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r \n"
1036 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1037 " 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"
1039 " f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1042 "# ifdef USESHADOWMAPPCF\n"
1043 "# if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1044 "# ifdef GL_ARB_texture_gather\n"
1045 "# define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1047 "# define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1049 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1050 " center *= ShadowMap_TextureScale;\n"
1051 " vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1052 " vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1053 " vec4 group3 = step(shadowmaptc.z, texval(-1.0, 1.0));\n"
1054 " vec4 group4 = step(shadowmaptc.z, texval( 1.0, 1.0));\n"
1055 " vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1056 " mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1057 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1059 "# ifdef GL_EXT_gpu_shader4\n"
1060 "# define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1062 "# define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r \n"
1064 "# if USESHADOWMAPPCF > 1\n"
1065 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1066 " center *= ShadowMap_TextureScale;\n"
1067 " 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"
1068 " vec4 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"
1069 " vec4 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"
1070 " vec4 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"
1071 " vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1072 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1074 " vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1075 " vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1076 " vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0, 0.0), texval( 0.0, 0.0), texval( 1.0, 0.0)));\n"
1077 " vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0, 1.0), texval( 0.0, 1.0), texval( 1.0, 1.0)));\n"
1078 " vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1079 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1083 " f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1090 "# ifdef USESHADOWMAPCUBE\n"
1091 "float ShadowMapCompare(vec3 dir)\n"
1093 " // apply depth texture cubemap as light filter\n"
1094 " vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1096 "# ifdef USESHADOWSAMPLER\n"
1097 " f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1099 " f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1106 "#ifdef MODE_WATER\n"
1111 "#ifdef USEOFFSETMAPPING\n"
1112 " // apply offsetmapping\n"
1113 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1114 "#define TexCoord TexCoordOffset\n"
1117 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1118 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1119 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1120 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1121 " // FIXME temporary hack to detect the case that the reflection\n"
1122 " // gets blackened at edges due to leaving the area that contains actual\n"
1124 " // Remove this 'ack once we have a better way to stop this thing from\n"
1126 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1127 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1128 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1129 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1130 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1131 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1132 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1133 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1134 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1135 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1136 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1137 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1140 "#else // !MODE_WATER\n"
1141 "#ifdef MODE_REFRACTION\n"
1143 "// refraction pass\n"
1146 "#ifdef USEOFFSETMAPPING\n"
1147 " // apply offsetmapping\n"
1148 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1149 "#define TexCoord TexCoordOffset\n"
1152 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1153 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1154 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1155 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1156 " // FIXME temporary hack to detect the case that the reflection\n"
1157 " // gets blackened at edges due to leaving the area that contains actual\n"
1159 " // Remove this 'ack once we have a better way to stop this thing from\n"
1161 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1162 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1163 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1164 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1165 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1166 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1169 "#else // !MODE_REFRACTION\n"
1172 "#ifdef USEOFFSETMAPPING\n"
1173 " // apply offsetmapping\n"
1174 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1175 "#define TexCoord TexCoordOffset\n"
1178 " // combine the diffuse textures (base, pants, shirt)\n"
1179 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1180 "#ifdef USECOLORMAPPING\n"
1181 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1183 "#ifdef USEVERTEXTEXTUREBLEND\n"
1184 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1185 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1186 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1187 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1189 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1192 "#ifdef USEDIFFUSE\n"
1193 " // get the surface normal and the gloss color\n"
1194 "# ifdef USEVERTEXTEXTUREBLEND\n"
1195 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1196 "# ifdef USESPECULAR\n"
1197 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1200 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1201 "# ifdef USESPECULAR\n"
1202 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1209 "#ifdef MODE_LIGHTSOURCE\n"
1210 " // light source\n"
1212 " // calculate surface normal, light normal, and specular normal\n"
1213 " // compute color intensity for the two textures (colormap and glossmap)\n"
1214 " // scale by light color and attenuation as efficiently as possible\n"
1215 " // (do as much scalar math as possible rather than vector math)\n"
1216 "# ifdef USEDIFFUSE\n"
1217 " // get the light normal\n"
1218 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1220 "# ifdef USESPECULAR\n"
1221 "# ifndef USEEXACTSPECULARMATH\n"
1222 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1225 " // calculate directional shading\n"
1226 "# ifdef USEEXACTSPECULARMATH\n"
1227 " 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"
1229 " 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"
1232 "# ifdef USEDIFFUSE\n"
1233 " // calculate directional shading\n"
1234 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1236 " // calculate directionless shading\n"
1237 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1241 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1242 "#if !showshadowmap\n"
1243 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1247 "# ifdef USECUBEFILTER\n"
1248 " // apply light cubemap filter\n"
1249 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1250 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1252 "#endif // MODE_LIGHTSOURCE\n"
1257 "#ifdef MODE_LIGHTDIRECTION\n"
1258 " // directional model lighting\n"
1259 "# ifdef USEDIFFUSE\n"
1260 " // get the light normal\n"
1261 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1263 "# ifdef USESPECULAR\n"
1264 " // calculate directional shading\n"
1265 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1266 "# ifdef USEEXACTSPECULARMATH\n"
1267 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1269 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1270 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1273 "# ifdef USEDIFFUSE\n"
1275 " // calculate directional shading\n"
1276 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1278 " color.rgb *= AmbientColor;\n"
1281 "#endif // MODE_LIGHTDIRECTION\n"
1286 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1287 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1289 " // get the light normal\n"
1290 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1291 " myhalf3 diffusenormal;\n"
1292 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1293 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1294 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1295 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1296 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1297 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1298 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1299 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1300 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1301 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1302 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1303 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1304 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1305 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1306 "# ifdef USESPECULAR\n"
1307 "# ifdef USEEXACTSPECULARMATH\n"
1308 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1310 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1311 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1315 " // apply lightmap color\n"
1316 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1317 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1322 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1323 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1325 " // get the light normal\n"
1326 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1327 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1328 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1329 "# ifdef USESPECULAR\n"
1330 "# ifdef USEEXACTSPECULARMATH\n"
1331 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1333 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1334 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1338 " // apply lightmap color\n"
1339 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1340 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1345 "#ifdef MODE_LIGHTMAP\n"
1346 " // apply lightmap color\n"
1347 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1348 "#endif // MODE_LIGHTMAP\n"
1353 "#ifdef MODE_VERTEXCOLOR\n"
1354 " // apply lightmap color\n"
1355 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1356 "#endif // MODE_VERTEXCOLOR\n"
1361 "#ifdef MODE_FLATCOLOR\n"
1362 "#endif // MODE_FLATCOLOR\n"
1370 " color *= TintColor;\n"
1373 "#ifdef USEVERTEXTEXTUREBLEND\n"
1374 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1376 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowColor;\n"
1380 " color.rgb *= SceneBrightness;\n"
1382 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1384 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1387 " // 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"
1388 "#ifdef USEREFLECTION\n"
1389 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1390 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1391 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1392 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1393 " // FIXME temporary hack to detect the case that the reflection\n"
1394 " // gets blackened at edges due to leaving the area that contains actual\n"
1396 " // Remove this 'ack once we have a better way to stop this thing from\n"
1398 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1399 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1400 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1401 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1402 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1403 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1406 " gl_FragColor = vec4(color);\n"
1408 "#if showshadowmap\n"
1409 "# ifdef USESHADOWMAPRECT\n"
1410 "# ifdef USESHADOWSAMPLER\n"
1411 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1413 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1416 "# ifdef USESHADOWMAP2D\n"
1417 "# ifdef USESHADOWSAMPLER\n"
1418 " gl_FragColor = shadow2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xyz);\n"
1420 " gl_FragColor = texture2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector).xy);\n"
1424 "# ifdef USESHADOWMAPCUBE\n"
1425 "# ifdef USESHADOWSAMPLER\n"
1426 " gl_FragColor = shadowCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector));\n"
1428 " gl_FragColor = textureCube(Texture_ShadowMapCube, GetShadowMapTCCube(CubeVector).xyz);\n"
1433 "#endif // !MODE_REFRACTION\n"
1434 "#endif // !MODE_WATER\n"
1436 "#endif // FRAGMENT_SHADER\n"
1438 "#endif // !MODE_GENERIC\n"
1439 "#endif // !MODE_POSTPROCESS\n"
1440 "#endif // !MODE_SHOWDEPTH\n"
1441 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1444 typedef struct shaderpermutationinfo_s
1446 const char *pretext;
1449 shaderpermutationinfo_t;
1451 typedef struct shadermodeinfo_s
1453 const char *vertexfilename;
1454 const char *geometryfilename;
1455 const char *fragmentfilename;
1456 const char *pretext;
1461 typedef enum shaderpermutation_e
1463 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1464 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1465 SHADERPERMUTATION_VIEWTINT = 1<<1, ///< view tint (postprocessing only)
1466 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1467 SHADERPERMUTATION_SATURATION = 1<<2, ///< saturation (postprocessing only)
1468 SHADERPERMUTATION_FOG = 1<<3, ///< tint the color by fog color or black if using additive blend mode
1469 SHADERPERMUTATION_GAMMARAMPS = 1<<3, ///< gamma (postprocessing only)
1470 SHADERPERMUTATION_CUBEFILTER = 1<<4, ///< (lightsource) use cubemap light filter
1471 SHADERPERMUTATION_GLOW = 1<<5, ///< (lightmap) blend in an additive glow texture
1472 SHADERPERMUTATION_BLOOM = 1<<5, ///< bloom (postprocessing only)
1473 SHADERPERMUTATION_SPECULAR = 1<<6, ///< (lightsource or deluxemapping) render specular effects
1474 SHADERPERMUTATION_POSTPROCESSING = 1<<6, ///< user defined postprocessing (postprocessing only)
1475 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<7, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1476 SHADERPERMUTATION_REFLECTION = 1<<8, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1477 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, ///< adjust texcoords to roughly simulate a displacement mapped surface
1478 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1479 SHADERPERMUTATION_SHADOWMAPRECT = 1<<11, ///< (lightsource) use shadowmap rectangle texture as light filter
1480 SHADERPERMUTATION_SHADOWMAPCUBE = 1<<12, ///< (lightsource) use shadowmap cubemap texture as light filter
1481 SHADERPERMUTATION_SHADOWMAP2D = 1<<13, ///< (lightsource) use shadowmap rectangle texture as light filter
1482 SHADERPERMUTATION_SHADOWMAPPCF = 1<<14, //< (lightsource) use percentage closer filtering on shadowmap test results
1483 SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<15, //< (lightsource) use higher quality percentage closer filtering on shadowmap test results
1484 SHADERPERMUTATION_SHADOWSAMPLER = 1<<16, //< (lightsource) use hardware shadowmap test
1485 SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<17, //< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
1486 SHADERPERMUTATION_LIMIT = 1<<18, ///< size of permutations array
1487 SHADERPERMUTATION_COUNT = 18 ///< size of shaderpermutationinfo array
1489 shaderpermutation_t;
1491 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1492 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1494 {"#define USEDIFFUSE\n", " diffuse"},
1495 {"#define USEVERTEXTEXTUREBLEND\n#define USEVIEWTINT\n", " vertextextureblend/tint"},
1496 {"#define USECOLORMAPPING\n#define USESATURATION\n", " colormapping/saturation"},
1497 {"#define USEFOG\n#define USEGAMMARAMPS\n", " fog/gammaramps"},
1498 {"#define USECUBEFILTER\n", " cubefilter"},
1499 {"#define USEGLOW\n#define USEBLOOM\n", " glow/bloom"},
1500 {"#define USESPECULAR\n#define USEPOSTPROCESSING", " specular/postprocessing"},
1501 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1502 {"#define USEREFLECTION\n", " reflection"},
1503 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1504 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1505 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1506 {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
1507 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
1508 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
1509 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
1510 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1511 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
1514 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1515 typedef enum shadermode_e
1517 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1518 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1519 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1520 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1521 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1522 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1523 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1524 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1525 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1526 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1527 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1528 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1529 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1534 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1535 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1537 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1538 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1539 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1540 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1541 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1542 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1543 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1544 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1545 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1546 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1547 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1548 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1549 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1552 struct r_glsl_permutation_s;
1553 typedef struct r_glsl_permutation_s
1555 /// hash lookup data
1556 struct r_glsl_permutation_s *hashnext;
1558 unsigned int permutation;
1560 /// indicates if we have tried compiling this permutation already
1562 /// 0 if compilation failed
1564 /// locations of detected uniforms in program object, or -1 if not found
1565 int loc_Texture_First;
1566 int loc_Texture_Second;
1567 int loc_Texture_GammaRamps;
1568 int loc_Texture_Normal;
1569 int loc_Texture_Color;
1570 int loc_Texture_Gloss;
1571 int loc_Texture_Glow;
1572 int loc_Texture_SecondaryNormal;
1573 int loc_Texture_SecondaryColor;
1574 int loc_Texture_SecondaryGloss;
1575 int loc_Texture_SecondaryGlow;
1576 int loc_Texture_Pants;
1577 int loc_Texture_Shirt;
1578 int loc_Texture_FogMask;
1579 int loc_Texture_Lightmap;
1580 int loc_Texture_Deluxemap;
1581 int loc_Texture_Attenuation;
1582 int loc_Texture_Cube;
1583 int loc_Texture_Refraction;
1584 int loc_Texture_Reflection;
1585 int loc_Texture_ShadowMapRect;
1586 int loc_Texture_ShadowMapCube;
1587 int loc_Texture_ShadowMap2D;
1588 int loc_Texture_CubeProjection;
1590 int loc_LightPosition;
1591 int loc_EyePosition;
1592 int loc_Color_Pants;
1593 int loc_Color_Shirt;
1594 int loc_FogRangeRecip;
1595 int loc_AmbientScale;
1596 int loc_DiffuseScale;
1597 int loc_SpecularScale;
1598 int loc_SpecularPower;
1600 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1601 int loc_OffsetMapping_Scale;
1603 int loc_AmbientColor;
1604 int loc_DiffuseColor;
1605 int loc_SpecularColor;
1607 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1608 int loc_GammaCoeff; ///< 1 / gamma
1609 int loc_DistortScaleRefractReflect;
1610 int loc_ScreenScaleRefractReflect;
1611 int loc_ScreenCenterRefractReflect;
1612 int loc_RefractColor;
1613 int loc_ReflectColor;
1614 int loc_ReflectFactor;
1615 int loc_ReflectOffset;
1623 int loc_ShadowMap_TextureScale;
1624 int loc_ShadowMap_Parameters;
1626 r_glsl_permutation_t;
1628 #define SHADERPERMUTATION_HASHSIZE 4096
1630 /// information about each possible shader permutation
1631 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1632 /// currently selected permutation
1633 r_glsl_permutation_t *r_glsl_permutation;
1634 /// storage for permutations linked in the hash table
1635 memexpandablearray_t r_glsl_permutationarray;
1637 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1639 //unsigned int hashdepth = 0;
1640 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1641 r_glsl_permutation_t *p;
1642 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1644 if (p->mode == mode && p->permutation == permutation)
1646 //if (hashdepth > 10)
1647 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1652 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1654 p->permutation = permutation;
1655 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1656 r_glsl_permutationhash[mode][hashindex] = p;
1657 //if (hashdepth > 10)
1658 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1662 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1665 if (!filename || !filename[0])
1667 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1670 if (printfromdisknotice)
1671 Con_DPrint("from disk... ");
1672 return shaderstring;
1674 else if (!strcmp(filename, "glsl/default.glsl"))
1676 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1677 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1679 return shaderstring;
1682 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1685 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1686 int vertstrings_count = 0;
1687 int geomstrings_count = 0;
1688 int fragstrings_count = 0;
1689 char *vertexstring, *geometrystring, *fragmentstring;
1690 const char *vertstrings_list[32+3];
1691 const char *geomstrings_list[32+3];
1692 const char *fragstrings_list[32+3];
1693 char permutationname[256];
1700 permutationname[0] = 0;
1701 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1702 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1703 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1705 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1707 // the first pretext is which type of shader to compile as
1708 // (later these will all be bound together as a program object)
1709 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1710 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1711 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1713 // the second pretext is the mode (for example a light source)
1714 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1715 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1716 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1717 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1719 // now add all the permutation pretexts
1720 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1722 if (permutation & (1<<i))
1724 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1725 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1726 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1727 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1731 // keep line numbers correct
1732 vertstrings_list[vertstrings_count++] = "\n";
1733 geomstrings_list[geomstrings_count++] = "\n";
1734 fragstrings_list[fragstrings_count++] = "\n";
1738 // now append the shader text itself
1739 vertstrings_list[vertstrings_count++] = vertexstring;
1740 geomstrings_list[geomstrings_count++] = geometrystring;
1741 fragstrings_list[fragstrings_count++] = fragmentstring;
1743 // if any sources were NULL, clear the respective list
1745 vertstrings_count = 0;
1746 if (!geometrystring)
1747 geomstrings_count = 0;
1748 if (!fragmentstring)
1749 fragstrings_count = 0;
1751 // compile the shader program
1752 if (vertstrings_count + geomstrings_count + fragstrings_count)
1753 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1757 qglUseProgramObjectARB(p->program);CHECKGLERROR
1758 // look up all the uniform variable names we care about, so we don't
1759 // have to look them up every time we set them
1760 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1761 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1762 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1763 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1764 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1765 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1766 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1767 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1768 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1769 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1770 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1771 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1772 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1773 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1774 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1775 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1776 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1777 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1778 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1779 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1780 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1781 p->loc_Texture_ShadowMapCube = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
1782 p->loc_Texture_ShadowMap2D = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
1783 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1784 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1785 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1786 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1787 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1788 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1789 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1790 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1791 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1792 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1793 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1794 p->loc_GlowColor = qglGetUniformLocationARB(p->program, "GlowColor");
1795 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1796 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1797 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1798 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1799 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1800 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1801 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1802 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1803 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1804 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1805 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1806 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1807 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1808 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1809 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1810 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1811 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1812 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1813 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1814 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1815 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1816 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1817 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1818 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1819 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1820 // initialize the samplers to refer to the texture units we use
1821 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1822 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1823 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1824 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1825 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1826 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1827 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1828 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1829 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1830 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1831 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1832 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1833 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1834 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1835 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1836 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1837 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1838 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1839 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1840 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1841 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1842 if (p->loc_Texture_ShadowMapCube >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube , GL20TU_SHADOWMAPCUBE);
1843 if (p->loc_Texture_ShadowMap2D >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D , GL20TU_SHADOWMAP2D);
1844 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1846 if (developer.integer)
1847 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1850 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1854 Mem_Free(vertexstring);
1856 Mem_Free(geometrystring);
1858 Mem_Free(fragmentstring);
1861 void R_GLSL_Restart_f(void)
1863 unsigned int i, limit;
1864 r_glsl_permutation_t *p;
1865 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1866 for (i = 0;i < limit;i++)
1868 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1870 GL_Backend_FreeProgram(p->program);
1871 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1874 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1877 void R_GLSL_DumpShader_f(void)
1881 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1884 Con_Printf("failed to write to glsl/default.glsl\n");
1888 FS_Print(file, "/* The engine may define the following macros:\n");
1889 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1890 for (i = 0;i < SHADERMODE_COUNT;i++)
1891 FS_Print(file, shadermodeinfo[i].pretext);
1892 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1893 FS_Print(file, shaderpermutationinfo[i].pretext);
1894 FS_Print(file, "*/\n");
1895 FS_Print(file, builtinshaderstring);
1898 Con_Printf("glsl/default.glsl written\n");
1901 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1903 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1904 if (r_glsl_permutation != perm)
1906 r_glsl_permutation = perm;
1907 if (!r_glsl_permutation->program)
1909 if (!r_glsl_permutation->compiled)
1910 R_GLSL_CompilePermutation(perm, mode, permutation);
1911 if (!r_glsl_permutation->program)
1913 // remove features until we find a valid permutation
1915 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1917 // reduce i more quickly whenever it would not remove any bits
1918 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1919 if (!(permutation & j))
1922 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1923 if (!r_glsl_permutation->compiled)
1924 R_GLSL_CompilePermutation(perm, mode, permutation);
1925 if (r_glsl_permutation->program)
1928 if (i >= SHADERPERMUTATION_COUNT)
1930 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");
1931 Cvar_SetValueQuick(&r_glsl, 0);
1932 R_GLSL_Restart_f(); // unload shaders
1933 return; // no bit left to clear
1938 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1942 void R_SetupGenericShader(qboolean usetexture)
1944 if (gl_support_fragment_shader)
1946 if (r_glsl.integer && r_glsl_usegeneric.integer)
1947 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1948 else if (r_glsl_permutation)
1950 r_glsl_permutation = NULL;
1951 qglUseProgramObjectARB(0);CHECKGLERROR
1956 void R_SetupGenericTwoTextureShader(int texturemode)
1958 if (gl_support_fragment_shader)
1960 if (r_glsl.integer && r_glsl_usegeneric.integer)
1961 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))));
1962 else if (r_glsl_permutation)
1964 r_glsl_permutation = NULL;
1965 qglUseProgramObjectARB(0);CHECKGLERROR
1968 if (!r_glsl_permutation)
1970 if (texturemode == GL_DECAL && gl_combine.integer)
1971 texturemode = GL_INTERPOLATE_ARB;
1972 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1976 void R_SetupDepthOrShadowShader(void)
1978 if (gl_support_fragment_shader)
1980 if (r_glsl.integer && r_glsl_usegeneric.integer)
1981 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1982 else if (r_glsl_permutation)
1984 r_glsl_permutation = NULL;
1985 qglUseProgramObjectARB(0);CHECKGLERROR
1990 void R_SetupShowDepthShader(void)
1992 if (gl_support_fragment_shader)
1994 if (r_glsl.integer && r_glsl_usegeneric.integer)
1995 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
1996 else if (r_glsl_permutation)
1998 r_glsl_permutation = NULL;
1999 qglUseProgramObjectARB(0);CHECKGLERROR
2004 extern rtexture_t *r_shadow_attenuationgradienttexture;
2005 extern rtexture_t *r_shadow_attenuation2dtexture;
2006 extern rtexture_t *r_shadow_attenuation3dtexture;
2007 extern qboolean r_shadow_usingshadowmaprect;
2008 extern qboolean r_shadow_usingshadowmapcube;
2009 extern qboolean r_shadow_usingshadowmap2d;
2010 extern float r_shadow_shadowmap_texturescale[2];
2011 extern float r_shadow_shadowmap_parameters[4];
2012 extern qboolean r_shadow_shadowmapvsdct;
2013 extern qboolean r_shadow_shadowmapsampler;
2014 extern int r_shadow_shadowmappcf;
2015 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
2017 // select a permutation of the lighting shader appropriate to this
2018 // combination of texture, entity, light source, and fogging, only use the
2019 // minimum features necessary to avoid wasting rendering time in the
2020 // fragment shader on features that are not being used
2021 unsigned int permutation = 0;
2022 unsigned int mode = 0;
2023 // TODO: implement geometry-shader based shadow volumes someday
2024 if (r_glsl_offsetmapping.integer)
2026 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2027 if (r_glsl_offsetmapping_reliefmapping.integer)
2028 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2030 if (rsurfacepass == RSURFPASS_BACKGROUND)
2032 // distorted background
2033 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2034 mode = SHADERMODE_WATER;
2036 mode = SHADERMODE_REFRACTION;
2038 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2041 mode = SHADERMODE_LIGHTSOURCE;
2042 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2043 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2044 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2045 permutation |= SHADERPERMUTATION_CUBEFILTER;
2046 if (diffusescale > 0)
2047 permutation |= SHADERPERMUTATION_DIFFUSE;
2048 if (specularscale > 0)
2049 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2050 if (r_refdef.fogenabled)
2051 permutation |= SHADERPERMUTATION_FOG;
2052 if (rsurface.texture->colormapping)
2053 permutation |= SHADERPERMUTATION_COLORMAPPING;
2054 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
2056 if (r_shadow_usingshadowmaprect)
2057 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
2058 if (r_shadow_usingshadowmap2d)
2059 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2060 if (r_shadow_usingshadowmapcube)
2061 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
2062 else if(r_shadow_shadowmapvsdct)
2063 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2065 if (r_shadow_shadowmapsampler)
2066 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2067 if (r_shadow_shadowmappcf > 1)
2068 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2069 else if (r_shadow_shadowmappcf)
2070 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2073 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2075 // unshaded geometry (fullbright or ambient model lighting)
2076 mode = SHADERMODE_FLATCOLOR;
2077 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2078 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2079 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2080 permutation |= SHADERPERMUTATION_GLOW;
2081 if (r_refdef.fogenabled)
2082 permutation |= SHADERPERMUTATION_FOG;
2083 if (rsurface.texture->colormapping)
2084 permutation |= SHADERPERMUTATION_COLORMAPPING;
2085 if (r_glsl_offsetmapping.integer)
2087 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2088 if (r_glsl_offsetmapping_reliefmapping.integer)
2089 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2091 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2092 permutation |= SHADERPERMUTATION_REFLECTION;
2094 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2096 // directional model lighting
2097 mode = SHADERMODE_LIGHTDIRECTION;
2098 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2099 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2100 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2101 permutation |= SHADERPERMUTATION_GLOW;
2102 permutation |= SHADERPERMUTATION_DIFFUSE;
2103 if (specularscale > 0)
2104 permutation |= SHADERPERMUTATION_SPECULAR;
2105 if (r_refdef.fogenabled)
2106 permutation |= SHADERPERMUTATION_FOG;
2107 if (rsurface.texture->colormapping)
2108 permutation |= SHADERPERMUTATION_COLORMAPPING;
2109 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2110 permutation |= SHADERPERMUTATION_REFLECTION;
2112 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2114 // ambient model lighting
2115 mode = SHADERMODE_LIGHTDIRECTION;
2116 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2117 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2118 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2119 permutation |= SHADERPERMUTATION_GLOW;
2120 if (r_refdef.fogenabled)
2121 permutation |= SHADERPERMUTATION_FOG;
2122 if (rsurface.texture->colormapping)
2123 permutation |= SHADERPERMUTATION_COLORMAPPING;
2124 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2125 permutation |= SHADERPERMUTATION_REFLECTION;
2130 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2132 // deluxemapping (light direction texture)
2133 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2134 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2136 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2137 permutation |= SHADERPERMUTATION_DIFFUSE;
2138 if (specularscale > 0)
2139 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2141 else if (r_glsl_deluxemapping.integer >= 2)
2143 // fake deluxemapping (uniform light direction in tangentspace)
2144 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2145 permutation |= SHADERPERMUTATION_DIFFUSE;
2146 if (specularscale > 0)
2147 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2149 else if (rsurface.uselightmaptexture)
2151 // ordinary lightmapping (q1bsp, q3bsp)
2152 mode = SHADERMODE_LIGHTMAP;
2156 // ordinary vertex coloring (q3bsp)
2157 mode = SHADERMODE_VERTEXCOLOR;
2159 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2160 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2161 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2162 permutation |= SHADERPERMUTATION_GLOW;
2163 if (r_refdef.fogenabled)
2164 permutation |= SHADERPERMUTATION_FOG;
2165 if (rsurface.texture->colormapping)
2166 permutation |= SHADERPERMUTATION_COLORMAPPING;
2167 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2168 permutation |= SHADERPERMUTATION_REFLECTION;
2170 if(permutation & SHADERPERMUTATION_SPECULAR)
2171 if(r_shadow_glossexact.integer)
2172 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2173 R_SetupShader_SetPermutation(mode, permutation);
2174 if (mode == SHADERMODE_LIGHTSOURCE)
2176 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2177 if (permutation & SHADERPERMUTATION_DIFFUSE)
2179 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2180 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2181 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2182 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2186 // ambient only is simpler
2187 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]);
2188 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2189 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2190 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2192 // additive passes are only darkened by fog, not tinted
2193 if (r_glsl_permutation->loc_FogColor >= 0)
2194 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2195 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2196 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]);
2200 if (mode == SHADERMODE_LIGHTDIRECTION)
2202 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);
2203 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);
2204 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);
2205 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]);
2209 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2210 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2211 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2213 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]);
2214 if (r_glsl_permutation->loc_GlowColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_GlowColor, rsurface.glowmod[0] * r_hdr_glowintensity.value, rsurface.glowmod[1] * r_hdr_glowintensity.value, rsurface.glowmod[2] * r_hdr_glowintensity.value);
2215 // additive passes are only darkened by fog, not tinted
2216 if (r_glsl_permutation->loc_FogColor >= 0)
2218 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2219 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2221 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2223 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);
2224 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]);
2225 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]);
2226 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2227 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2228 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2229 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2231 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2232 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
2233 if (r_glsl_permutation->loc_Color_Pants >= 0)
2235 if (rsurface.texture->currentskinframe->pants)
2236 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2238 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2240 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2242 if (rsurface.texture->currentskinframe->shirt)
2243 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2245 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2247 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
2248 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2250 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2254 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2256 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2260 #define SKINFRAME_HASH 1024
2264 int loadsequence; // incremented each level change
2265 memexpandablearray_t array;
2266 skinframe_t *hash[SKINFRAME_HASH];
2269 r_skinframe_t r_skinframe;
2271 void R_SkinFrame_PrepareForPurge(void)
2273 r_skinframe.loadsequence++;
2274 // wrap it without hitting zero
2275 if (r_skinframe.loadsequence >= 200)
2276 r_skinframe.loadsequence = 1;
2279 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2283 // mark the skinframe as used for the purging code
2284 skinframe->loadsequence = r_skinframe.loadsequence;
2287 void R_SkinFrame_Purge(void)
2291 for (i = 0;i < SKINFRAME_HASH;i++)
2293 for (s = r_skinframe.hash[i];s;s = s->next)
2295 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2297 if (s->merged == s->base)
2299 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2300 R_PurgeTexture(s->stain );s->stain = NULL;
2301 R_PurgeTexture(s->merged);s->merged = NULL;
2302 R_PurgeTexture(s->base );s->base = NULL;
2303 R_PurgeTexture(s->pants );s->pants = NULL;
2304 R_PurgeTexture(s->shirt );s->shirt = NULL;
2305 R_PurgeTexture(s->nmap );s->nmap = NULL;
2306 R_PurgeTexture(s->gloss );s->gloss = NULL;
2307 R_PurgeTexture(s->glow );s->glow = NULL;
2308 R_PurgeTexture(s->fog );s->fog = NULL;
2309 s->loadsequence = 0;
2315 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2317 char basename[MAX_QPATH];
2319 Image_StripImageExtension(name, basename, sizeof(basename));
2321 if( last == NULL ) {
2323 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2324 item = r_skinframe.hash[hashindex];
2329 // linearly search through the hash bucket
2330 for( ; item ; item = item->next ) {
2331 if( !strcmp( item->basename, basename ) ) {
2338 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2342 char basename[MAX_QPATH];
2344 Image_StripImageExtension(name, basename, sizeof(basename));
2346 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2347 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2348 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2352 rtexture_t *dyntexture;
2353 // check whether its a dynamic texture
2354 dyntexture = CL_GetDynTexture( basename );
2355 if (!add && !dyntexture)
2357 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2358 memset(item, 0, sizeof(*item));
2359 strlcpy(item->basename, basename, sizeof(item->basename));
2360 item->base = dyntexture; // either NULL or dyntexture handle
2361 item->textureflags = textureflags;
2362 item->comparewidth = comparewidth;
2363 item->compareheight = compareheight;
2364 item->comparecrc = comparecrc;
2365 item->next = r_skinframe.hash[hashindex];
2366 r_skinframe.hash[hashindex] = item;
2368 else if( item->base == NULL )
2370 rtexture_t *dyntexture;
2371 // check whether its a dynamic texture
2372 // 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]
2373 dyntexture = CL_GetDynTexture( basename );
2374 item->base = dyntexture; // either NULL or dyntexture handle
2377 R_SkinFrame_MarkUsed(item);
2381 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2383 unsigned long long avgcolor[5], wsum; \
2391 for(pix = 0; pix < cnt; ++pix) \
2394 for(comp = 0; comp < 3; ++comp) \
2396 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2399 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2401 for(comp = 0; comp < 3; ++comp) \
2402 avgcolor[comp] += getpixel * w; \
2405 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2406 avgcolor[4] += getpixel; \
2408 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2410 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2411 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2412 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2413 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2416 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2418 // FIXME: it should be possible to disable loading various layers using
2419 // cvars, to prevent wasted loading time and memory usage if the user does
2421 qboolean loadnormalmap = true;
2422 qboolean loadgloss = true;
2423 qboolean loadpantsandshirt = true;
2424 qboolean loadglow = true;
2426 unsigned char *pixels;
2427 unsigned char *bumppixels;
2428 unsigned char *basepixels = NULL;
2429 int basepixels_width;
2430 int basepixels_height;
2431 skinframe_t *skinframe;
2435 if (cls.state == ca_dedicated)
2438 // return an existing skinframe if already loaded
2439 // if loading of the first image fails, don't make a new skinframe as it
2440 // would cause all future lookups of this to be missing
2441 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2442 if (skinframe && skinframe->base)
2445 basepixels = loadimagepixelsbgra(name, complain, true);
2446 if (basepixels == NULL)
2449 if (developer_loading.integer)
2450 Con_Printf("loading skin \"%s\"\n", name);
2452 // we've got some pixels to store, so really allocate this new texture now
2454 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2455 skinframe->stain = NULL;
2456 skinframe->merged = NULL;
2457 skinframe->base = r_texture_notexture;
2458 skinframe->pants = NULL;
2459 skinframe->shirt = NULL;
2460 skinframe->nmap = r_texture_blanknormalmap;
2461 skinframe->gloss = NULL;
2462 skinframe->glow = NULL;
2463 skinframe->fog = NULL;
2465 basepixels_width = image_width;
2466 basepixels_height = image_height;
2467 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);
2469 if (textureflags & TEXF_ALPHA)
2471 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2472 if (basepixels[j] < 255)
2474 if (j < basepixels_width * basepixels_height * 4)
2476 // has transparent pixels
2478 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2479 for (j = 0;j < image_width * image_height * 4;j += 4)
2484 pixels[j+3] = basepixels[j+3];
2486 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);
2491 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2492 //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]);
2494 // _norm is the name used by tenebrae and has been adopted as standard
2497 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2499 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);
2503 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2505 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2506 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2507 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);
2509 Mem_Free(bumppixels);
2511 else if (r_shadow_bumpscale_basetexture.value > 0)
2513 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2514 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2515 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);
2519 // _luma is supported for tenebrae compatibility
2520 // (I think it's a very stupid name, but oh well)
2521 // _glow is the preferred name
2522 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;}
2523 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;}
2524 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;}
2525 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;}
2528 Mem_Free(basepixels);
2533 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2536 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2539 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)
2544 for (i = 0;i < width*height;i++)
2545 if (((unsigned char *)&palette[in[i]])[3] > 0)
2547 if (i == width*height)
2550 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2553 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2554 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2557 unsigned char *temp1, *temp2;
2558 skinframe_t *skinframe;
2560 if (cls.state == ca_dedicated)
2563 // if already loaded just return it, otherwise make a new skinframe
2564 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2565 if (skinframe && skinframe->base)
2568 skinframe->stain = NULL;
2569 skinframe->merged = NULL;
2570 skinframe->base = r_texture_notexture;
2571 skinframe->pants = NULL;
2572 skinframe->shirt = NULL;
2573 skinframe->nmap = r_texture_blanknormalmap;
2574 skinframe->gloss = NULL;
2575 skinframe->glow = NULL;
2576 skinframe->fog = NULL;
2578 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2582 if (developer_loading.integer)
2583 Con_Printf("loading 32bit skin \"%s\"\n", name);
2585 if (r_shadow_bumpscale_basetexture.value > 0)
2587 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2588 temp2 = temp1 + width * height * 4;
2589 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2590 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2593 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2594 if (textureflags & TEXF_ALPHA)
2596 for (i = 3;i < width * height * 4;i += 4)
2597 if (skindata[i] < 255)
2599 if (i < width * height * 4)
2601 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2602 memcpy(fogpixels, skindata, width * height * 4);
2603 for (i = 0;i < width * height * 4;i += 4)
2604 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2605 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2606 Mem_Free(fogpixels);
2610 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2611 //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]);
2616 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2619 unsigned char *temp1, *temp2;
2620 unsigned int *palette;
2621 skinframe_t *skinframe;
2623 if (cls.state == ca_dedicated)
2626 // if already loaded just return it, otherwise make a new skinframe
2627 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2628 if (skinframe && skinframe->base)
2631 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2633 skinframe->stain = NULL;
2634 skinframe->merged = NULL;
2635 skinframe->base = r_texture_notexture;
2636 skinframe->pants = NULL;
2637 skinframe->shirt = NULL;
2638 skinframe->nmap = r_texture_blanknormalmap;
2639 skinframe->gloss = NULL;
2640 skinframe->glow = NULL;
2641 skinframe->fog = NULL;
2643 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2647 if (developer_loading.integer)
2648 Con_Printf("loading quake skin \"%s\"\n", name);
2650 if (r_shadow_bumpscale_basetexture.value > 0)
2652 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2653 temp2 = temp1 + width * height * 4;
2654 // use either a custom palette or the quake palette
2655 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2656 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2657 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2660 // use either a custom palette, or the quake palette
2661 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2662 if (loadglowtexture)
2663 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2664 if (loadpantsandshirt)
2666 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2667 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2669 if (skinframe->pants || skinframe->shirt)
2670 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
2671 if (textureflags & TEXF_ALPHA)
2673 for (i = 0;i < width * height;i++)
2674 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2676 if (i < width * height)
2677 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2680 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2681 //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]);
2686 skinframe_t *R_SkinFrame_LoadMissing(void)
2688 skinframe_t *skinframe;
2690 if (cls.state == ca_dedicated)
2693 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2694 skinframe->stain = NULL;
2695 skinframe->merged = NULL;
2696 skinframe->base = r_texture_notexture;
2697 skinframe->pants = NULL;
2698 skinframe->shirt = NULL;
2699 skinframe->nmap = r_texture_blanknormalmap;
2700 skinframe->gloss = NULL;
2701 skinframe->glow = NULL;
2702 skinframe->fog = NULL;
2704 skinframe->avgcolor[0] = rand() / RAND_MAX;
2705 skinframe->avgcolor[1] = rand() / RAND_MAX;
2706 skinframe->avgcolor[2] = rand() / RAND_MAX;
2707 skinframe->avgcolor[3] = 1;
2712 void gl_main_start(void)
2716 memset(r_queries, 0, sizeof(r_queries));
2718 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2719 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2721 // set up r_skinframe loading system for textures
2722 memset(&r_skinframe, 0, sizeof(r_skinframe));
2723 r_skinframe.loadsequence = 1;
2724 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2726 r_main_texturepool = R_AllocTexturePool();
2727 R_BuildBlankTextures();
2729 if (gl_texturecubemap)
2732 R_BuildNormalizationCube();
2734 r_texture_fogattenuation = NULL;
2735 r_texture_gammaramps = NULL;
2736 //r_texture_fogintensity = NULL;
2737 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2738 memset(&r_waterstate, 0, sizeof(r_waterstate));
2739 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2740 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2741 memset(&r_svbsp, 0, sizeof (r_svbsp));
2743 r_refdef.fogmasktable_density = 0;
2746 extern rtexture_t *loadingscreentexture;
2747 void gl_main_shutdown(void)
2750 qglDeleteQueriesARB(r_maxqueries, r_queries);
2754 memset(r_queries, 0, sizeof(r_queries));
2756 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2757 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2759 // clear out the r_skinframe state
2760 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2761 memset(&r_skinframe, 0, sizeof(r_skinframe));
2764 Mem_Free(r_svbsp.nodes);
2765 memset(&r_svbsp, 0, sizeof (r_svbsp));
2766 R_FreeTexturePool(&r_main_texturepool);
2767 loadingscreentexture = NULL;
2768 r_texture_blanknormalmap = NULL;
2769 r_texture_white = NULL;
2770 r_texture_grey128 = NULL;
2771 r_texture_black = NULL;
2772 r_texture_whitecube = NULL;
2773 r_texture_normalizationcube = NULL;
2774 r_texture_fogattenuation = NULL;
2775 r_texture_gammaramps = NULL;
2776 //r_texture_fogintensity = NULL;
2777 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2778 memset(&r_waterstate, 0, sizeof(r_waterstate));
2782 extern void CL_ParseEntityLump(char *entitystring);
2783 void gl_main_newmap(void)
2785 // FIXME: move this code to client
2787 char *entities, entname[MAX_QPATH];
2790 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2791 l = (int)strlen(entname) - 4;
2792 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2794 memcpy(entname + l, ".ent", 5);
2795 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2797 CL_ParseEntityLump(entities);
2802 if (cl.worldmodel->brush.entities)
2803 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2807 void GL_Main_Init(void)
2809 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2811 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2812 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2813 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2814 if (gamemode == GAME_NEHAHRA)
2816 Cvar_RegisterVariable (&gl_fogenable);
2817 Cvar_RegisterVariable (&gl_fogdensity);
2818 Cvar_RegisterVariable (&gl_fogred);
2819 Cvar_RegisterVariable (&gl_foggreen);
2820 Cvar_RegisterVariable (&gl_fogblue);
2821 Cvar_RegisterVariable (&gl_fogstart);
2822 Cvar_RegisterVariable (&gl_fogend);
2823 Cvar_RegisterVariable (&gl_skyclip);
2825 Cvar_RegisterVariable(&r_motionblur);
2826 Cvar_RegisterVariable(&r_motionblur_maxblur);
2827 Cvar_RegisterVariable(&r_motionblur_bmin);
2828 Cvar_RegisterVariable(&r_motionblur_vmin);
2829 Cvar_RegisterVariable(&r_motionblur_vmax);
2830 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2831 Cvar_RegisterVariable(&r_motionblur_randomize);
2832 Cvar_RegisterVariable(&r_damageblur);
2833 Cvar_RegisterVariable(&r_animcache);
2834 Cvar_RegisterVariable(&r_depthfirst);
2835 Cvar_RegisterVariable(&r_useinfinitefarclip);
2836 Cvar_RegisterVariable(&r_nearclip);
2837 Cvar_RegisterVariable(&r_showbboxes);
2838 Cvar_RegisterVariable(&r_showsurfaces);
2839 Cvar_RegisterVariable(&r_showtris);
2840 Cvar_RegisterVariable(&r_shownormals);
2841 Cvar_RegisterVariable(&r_showlighting);
2842 Cvar_RegisterVariable(&r_showshadowvolumes);
2843 Cvar_RegisterVariable(&r_showcollisionbrushes);
2844 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2845 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2846 Cvar_RegisterVariable(&r_showdisabledepthtest);
2847 Cvar_RegisterVariable(&r_drawportals);
2848 Cvar_RegisterVariable(&r_drawentities);
2849 Cvar_RegisterVariable(&r_cullentities_trace);
2850 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2851 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2852 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2853 Cvar_RegisterVariable(&r_drawviewmodel);
2854 Cvar_RegisterVariable(&r_speeds);
2855 Cvar_RegisterVariable(&r_fullbrights);
2856 Cvar_RegisterVariable(&r_wateralpha);
2857 Cvar_RegisterVariable(&r_dynamic);
2858 Cvar_RegisterVariable(&r_fullbright);
2859 Cvar_RegisterVariable(&r_shadows);
2860 Cvar_RegisterVariable(&r_shadows_darken);
2861 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
2862 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
2863 Cvar_RegisterVariable(&r_shadows_throwdistance);
2864 Cvar_RegisterVariable(&r_shadows_throwdirection);
2865 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2866 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2867 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2868 Cvar_RegisterVariable(&r_fog_exp2);
2869 Cvar_RegisterVariable(&r_drawfog);
2870 Cvar_RegisterVariable(&r_textureunits);
2871 Cvar_RegisterVariable(&r_glsl);
2872 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2873 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2874 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2875 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2876 Cvar_RegisterVariable(&r_glsl_postprocess);
2877 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2878 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2879 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2880 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2881 Cvar_RegisterVariable(&r_glsl_usegeneric);
2882 Cvar_RegisterVariable(&r_water);
2883 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2884 Cvar_RegisterVariable(&r_water_clippingplanebias);
2885 Cvar_RegisterVariable(&r_water_refractdistort);
2886 Cvar_RegisterVariable(&r_water_reflectdistort);
2887 Cvar_RegisterVariable(&r_lerpsprites);
2888 Cvar_RegisterVariable(&r_lerpmodels);
2889 Cvar_RegisterVariable(&r_lerplightstyles);
2890 Cvar_RegisterVariable(&r_waterscroll);
2891 Cvar_RegisterVariable(&r_bloom);
2892 Cvar_RegisterVariable(&r_bloom_colorscale);
2893 Cvar_RegisterVariable(&r_bloom_brighten);
2894 Cvar_RegisterVariable(&r_bloom_blur);
2895 Cvar_RegisterVariable(&r_bloom_resolution);
2896 Cvar_RegisterVariable(&r_bloom_colorexponent);
2897 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2898 Cvar_RegisterVariable(&r_hdr);
2899 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2900 Cvar_RegisterVariable(&r_hdr_glowintensity);
2901 Cvar_RegisterVariable(&r_hdr_range);
2902 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2903 Cvar_RegisterVariable(&developer_texturelogging);
2904 Cvar_RegisterVariable(&gl_lightmaps);
2905 Cvar_RegisterVariable(&r_test);
2906 Cvar_RegisterVariable(&r_batchmode);
2907 Cvar_RegisterVariable(&r_glsl_saturation);
2908 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2909 Cvar_SetValue("r_fullbrights", 0);
2910 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2912 Cvar_RegisterVariable(&r_track_sprites);
2913 Cvar_RegisterVariable(&r_track_sprites_flags);
2914 Cvar_RegisterVariable(&r_track_sprites_scalew);
2915 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2918 extern void R_Textures_Init(void);
2919 extern void GL_Draw_Init(void);
2920 extern void GL_Main_Init(void);
2921 extern void R_Shadow_Init(void);
2922 extern void R_Sky_Init(void);
2923 extern void GL_Surf_Init(void);
2924 extern void R_Particles_Init(void);
2925 extern void R_Explosion_Init(void);
2926 extern void gl_backend_init(void);
2927 extern void Sbar_Init(void);
2928 extern void R_LightningBeams_Init(void);
2929 extern void Mod_RenderInit(void);
2931 void Render_Init(void)
2943 R_LightningBeams_Init();
2952 extern char *ENGINE_EXTENSIONS;
2955 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2956 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2957 gl_version = (const char *)qglGetString(GL_VERSION);
2958 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2962 if (!gl_platformextensions)
2963 gl_platformextensions = "";
2965 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2966 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2967 Con_Printf("GL_VERSION: %s\n", gl_version);
2968 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2969 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2971 VID_CheckExtensions();
2973 // LordHavoc: report supported extensions
2974 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2976 // clear to black (loading plaque will be seen over this)
2978 qglClearColor(0,0,0,1);CHECKGLERROR
2979 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2982 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2986 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2988 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2991 p = r_refdef.view.frustum + i;
2996 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3000 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3004 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3008 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3012 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3016 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3020 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3024 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3032 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3036 for (i = 0;i < numplanes;i++)
3043 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3047 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3051 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3055 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3059 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3063 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3067 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3071 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3079 //==================================================================================
3081 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3084 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3085 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3086 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3089 typedef struct r_animcache_entity_s
3096 qboolean wantnormals;
3097 qboolean wanttangents;
3099 r_animcache_entity_t;
3101 typedef struct r_animcache_s
3103 r_animcache_entity_t entity[MAX_EDICTS*2];
3109 static r_animcache_t r_animcachestate;
3111 void R_AnimCache_Free(void)
3114 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3116 r_animcachestate.entity[idx].maxvertices = 0;
3117 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3118 r_animcachestate.entity[idx].vertex3f = NULL;
3119 r_animcachestate.entity[idx].normal3f = NULL;
3120 r_animcachestate.entity[idx].svector3f = NULL;
3121 r_animcachestate.entity[idx].tvector3f = NULL;
3123 r_animcachestate.currentindex = 0;
3124 r_animcachestate.maxindex = 0;
3127 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3131 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3133 if (cache->maxvertices >= numvertices)
3136 // Release existing memory
3137 if (cache->vertex3f)
3138 Mem_Free(cache->vertex3f);
3140 // Pad by 1024 verts
3141 cache->maxvertices = (numvertices + 1023) & ~1023;
3142 arraySize = cache->maxvertices * 3;
3144 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3145 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3146 r_animcachestate.entity[cacheIdx].vertex3f = base;
3147 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3148 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3149 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3151 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3154 void R_AnimCache_NewFrame(void)
3158 if (r_animcache.integer && r_drawentities.integer)
3159 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3160 else if (r_animcachestate.maxindex)
3163 r_animcachestate.currentindex = 0;
3165 for (i = 0;i < r_refdef.scene.numentities;i++)
3166 r_refdef.scene.entities[i]->animcacheindex = -1;
3169 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3171 dp_model_t *model = ent->model;
3172 r_animcache_entity_t *c;
3173 // see if it's already cached this frame
3174 if (ent->animcacheindex >= 0)
3176 // add normals/tangents if needed
3177 c = r_animcachestate.entity + ent->animcacheindex;
3179 wantnormals = false;
3180 if (c->wanttangents)
3181 wanttangents = false;
3182 if (wantnormals || wanttangents)
3183 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3187 // see if this ent is worth caching
3188 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3190 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3192 // assign it a cache entry and make sure the arrays are big enough
3193 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3194 ent->animcacheindex = r_animcachestate.currentindex++;
3195 c = r_animcachestate.entity + ent->animcacheindex;
3196 c->wantnormals = wantnormals;
3197 c->wanttangents = wanttangents;
3198 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3203 void R_AnimCache_CacheVisibleEntities(void)
3206 qboolean wantnormals;
3207 qboolean wanttangents;
3209 if (!r_animcachestate.maxindex)
3212 wantnormals = !r_showsurfaces.integer;
3213 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3215 // TODO: thread this?
3217 for (i = 0;i < r_refdef.scene.numentities;i++)
3219 if (!r_refdef.viewcache.entityvisible[i])
3221 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3225 //==================================================================================
3227 static void R_View_UpdateEntityLighting (void)
3230 entity_render_t *ent;
3231 vec3_t tempdiffusenormal;
3233 for (i = 0;i < r_refdef.scene.numentities;i++)
3235 ent = r_refdef.scene.entities[i];
3237 // skip unseen models
3238 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3242 if (ent->model && ent->model->brush.num_leafs)
3244 // TODO: use modellight for r_ambient settings on world?
3245 VectorSet(ent->modellight_ambient, 0, 0, 0);
3246 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3247 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3251 // fetch the lighting from the worldmodel data
3252 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));
3253 VectorClear(ent->modellight_diffuse);
3254 VectorClear(tempdiffusenormal);
3255 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3258 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3259 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3262 VectorSet(ent->modellight_ambient, 1, 1, 1);
3264 // move the light direction into modelspace coordinates for lighting code
3265 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3266 if(VectorLength2(ent->modellight_lightdir) == 0)
3267 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3268 VectorNormalize(ent->modellight_lightdir);
3272 #define MAX_LINEOFSIGHTTRACES 64
3274 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3277 vec3_t boxmins, boxmaxs;
3280 dp_model_t *model = r_refdef.scene.worldmodel;
3282 if (!model || !model->brush.TraceLineOfSight)
3285 // expand the box a little
3286 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3287 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3288 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3289 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3290 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3291 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3294 VectorCopy(eye, start);
3295 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3296 if (model->brush.TraceLineOfSight(model, start, end))
3299 // try various random positions
3300 for (i = 0;i < numsamples;i++)
3302 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3303 if (model->brush.TraceLineOfSight(model, start, end))
3311 static void R_View_UpdateEntityVisible (void)
3314 entity_render_t *ent;
3316 if (!r_drawentities.integer)
3319 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3320 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3322 // worldmodel can check visibility
3323 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3324 for (i = 0;i < r_refdef.scene.numentities;i++)
3326 ent = r_refdef.scene.entities[i];
3327 if (!(ent->flags & renderimask))
3328 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)))
3329 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))
3330 r_refdef.viewcache.entityvisible[i] = true;
3332 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3334 for (i = 0;i < r_refdef.scene.numentities;i++)
3336 ent = r_refdef.scene.entities[i];
3337 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & (RENDER_VIEWMODEL + RENDER_NOCULL)) && !(ent->model && (ent->model->name[0] == '*')))
3339 if(R_CanSeeBox(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3340 ent->last_trace_visibility = realtime;
3341 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3342 r_refdef.viewcache.entityvisible[i] = 0;
3349 // no worldmodel or it can't check visibility
3350 for (i = 0;i < r_refdef.scene.numentities;i++)
3352 ent = r_refdef.scene.entities[i];
3353 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));
3358 /// only used if skyrendermasked, and normally returns false
3359 int R_DrawBrushModelsSky (void)
3362 entity_render_t *ent;
3364 if (!r_drawentities.integer)
3368 for (i = 0;i < r_refdef.scene.numentities;i++)
3370 if (!r_refdef.viewcache.entityvisible[i])
3372 ent = r_refdef.scene.entities[i];
3373 if (!ent->model || !ent->model->DrawSky)
3375 ent->model->DrawSky(ent);
3381 static void R_DrawNoModel(entity_render_t *ent);
3382 static void R_DrawModels(void)
3385 entity_render_t *ent;
3387 if (!r_drawentities.integer)
3390 for (i = 0;i < r_refdef.scene.numentities;i++)
3392 if (!r_refdef.viewcache.entityvisible[i])
3394 ent = r_refdef.scene.entities[i];
3395 r_refdef.stats.entities++;
3396 if (ent->model && ent->model->Draw != NULL)
3397 ent->model->Draw(ent);
3403 static void R_DrawModelsDepth(void)
3406 entity_render_t *ent;
3408 if (!r_drawentities.integer)
3411 for (i = 0;i < r_refdef.scene.numentities;i++)
3413 if (!r_refdef.viewcache.entityvisible[i])
3415 ent = r_refdef.scene.entities[i];
3416 if (ent->model && ent->model->DrawDepth != NULL)
3417 ent->model->DrawDepth(ent);
3421 static void R_DrawModelsDebug(void)
3424 entity_render_t *ent;
3426 if (!r_drawentities.integer)
3429 for (i = 0;i < r_refdef.scene.numentities;i++)
3431 if (!r_refdef.viewcache.entityvisible[i])
3433 ent = r_refdef.scene.entities[i];
3434 if (ent->model && ent->model->DrawDebug != NULL)
3435 ent->model->DrawDebug(ent);
3439 static void R_DrawModelsAddWaterPlanes(void)
3442 entity_render_t *ent;
3444 if (!r_drawentities.integer)
3447 for (i = 0;i < r_refdef.scene.numentities;i++)
3449 if (!r_refdef.viewcache.entityvisible[i])
3451 ent = r_refdef.scene.entities[i];
3452 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3453 ent->model->DrawAddWaterPlanes(ent);
3457 static void R_View_SetFrustum(void)
3460 double slopex, slopey;
3461 vec3_t forward, left, up, origin;
3463 // we can't trust r_refdef.view.forward and friends in reflected scenes
3464 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3467 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3468 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3469 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3470 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3471 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3472 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3473 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3474 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3475 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3476 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3477 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3478 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3482 zNear = r_refdef.nearclip;
3483 nudge = 1.0 - 1.0 / (1<<23);
3484 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3485 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3486 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3487 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3488 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3489 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3490 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3491 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3497 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3498 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3499 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3500 r_refdef.view.frustum[0].dist = m[15] - m[12];
3502 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3503 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3504 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3505 r_refdef.view.frustum[1].dist = m[15] + m[12];
3507 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3508 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3509 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3510 r_refdef.view.frustum[2].dist = m[15] - m[13];
3512 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3513 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3514 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3515 r_refdef.view.frustum[3].dist = m[15] + m[13];
3517 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3518 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3519 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3520 r_refdef.view.frustum[4].dist = m[15] - m[14];
3522 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3523 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3524 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3525 r_refdef.view.frustum[5].dist = m[15] + m[14];
3528 if (r_refdef.view.useperspective)
3530 slopex = 1.0 / r_refdef.view.frustum_x;
3531 slopey = 1.0 / r_refdef.view.frustum_y;
3532 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3533 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3534 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3535 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3536 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3538 // Leaving those out was a mistake, those were in the old code, and they
3539 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3540 // I couldn't reproduce it after adding those normalizations. --blub
3541 VectorNormalize(r_refdef.view.frustum[0].normal);
3542 VectorNormalize(r_refdef.view.frustum[1].normal);
3543 VectorNormalize(r_refdef.view.frustum[2].normal);
3544 VectorNormalize(r_refdef.view.frustum[3].normal);
3546 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3547 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]);
3548 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]);
3549 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]);
3550 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]);
3552 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3553 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3554 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3555 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3556 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3560 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3561 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3562 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3563 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3564 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3565 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3566 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3567 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3568 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3569 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3571 r_refdef.view.numfrustumplanes = 5;
3573 if (r_refdef.view.useclipplane)
3575 r_refdef.view.numfrustumplanes = 6;
3576 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3579 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3580 PlaneClassify(r_refdef.view.frustum + i);
3582 // LordHavoc: note to all quake engine coders, Quake had a special case
3583 // for 90 degrees which assumed a square view (wrong), so I removed it,
3584 // Quake2 has it disabled as well.
3586 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3587 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3588 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3589 //PlaneClassify(&frustum[0]);
3591 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3592 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3593 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3594 //PlaneClassify(&frustum[1]);
3596 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3597 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3598 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3599 //PlaneClassify(&frustum[2]);
3601 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3602 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3603 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3604 //PlaneClassify(&frustum[3]);
3607 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3608 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3609 //PlaneClassify(&frustum[4]);
3612 void R_View_Update(void)
3614 R_View_SetFrustum();
3615 R_View_WorldVisibility(r_refdef.view.useclipplane);
3616 R_View_UpdateEntityVisible();
3617 R_View_UpdateEntityLighting();
3620 void R_SetupView(qboolean allowwaterclippingplane)
3622 const double *customclipplane = NULL;
3624 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3626 // LordHavoc: couldn't figure out how to make this approach the
3627 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3628 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3629 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3630 dist = r_refdef.view.clipplane.dist;
3631 plane[0] = r_refdef.view.clipplane.normal[0];
3632 plane[1] = r_refdef.view.clipplane.normal[1];
3633 plane[2] = r_refdef.view.clipplane.normal[2];
3635 customclipplane = plane;
3638 if (!r_refdef.view.useperspective)
3639 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);
3640 else if (gl_stencil && r_useinfinitefarclip.integer)
3641 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);
3643 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);
3644 R_SetViewport(&r_refdef.view.viewport);
3647 void R_ResetViewRendering2D(void)
3649 r_viewport_t viewport;
3652 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3653 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);
3654 R_SetViewport(&viewport);
3655 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3656 GL_Color(1, 1, 1, 1);
3657 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3658 GL_BlendFunc(GL_ONE, GL_ZERO);
3659 GL_AlphaTest(false);
3660 GL_ScissorTest(false);
3661 GL_DepthMask(false);
3662 GL_DepthRange(0, 1);
3663 GL_DepthTest(false);
3664 R_Mesh_Matrix(&identitymatrix);
3665 R_Mesh_ResetTextureState();
3666 GL_PolygonOffset(0, 0);
3667 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3668 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3669 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3670 qglStencilMask(~0);CHECKGLERROR
3671 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3672 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3673 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3674 R_SetupGenericShader(true);
3677 void R_ResetViewRendering3D(void)
3682 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3683 GL_Color(1, 1, 1, 1);
3684 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3685 GL_BlendFunc(GL_ONE, GL_ZERO);
3686 GL_AlphaTest(false);
3687 GL_ScissorTest(true);
3689 GL_DepthRange(0, 1);
3691 R_Mesh_Matrix(&identitymatrix);
3692 R_Mesh_ResetTextureState();
3693 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3694 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3695 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3696 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3697 qglStencilMask(~0);CHECKGLERROR
3698 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3699 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3700 GL_CullFace(r_refdef.view.cullface_back);
3701 R_SetupGenericShader(true);
3704 void R_RenderScene(void);
3705 void R_RenderWaterPlanes(void);
3707 static void R_Water_StartFrame(void)
3710 int waterwidth, waterheight, texturewidth, textureheight;
3711 r_waterstate_waterplane_t *p;
3713 // set waterwidth and waterheight to the water resolution that will be
3714 // used (often less than the screen resolution for faster rendering)
3715 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3716 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3718 // calculate desired texture sizes
3719 // can't use water if the card does not support the texture size
3720 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3721 texturewidth = textureheight = waterwidth = waterheight = 0;
3722 else if (gl_support_arb_texture_non_power_of_two)
3724 texturewidth = waterwidth;
3725 textureheight = waterheight;
3729 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3730 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3733 // allocate textures as needed
3734 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3736 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3737 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3739 if (p->texture_refraction)
3740 R_FreeTexture(p->texture_refraction);
3741 p->texture_refraction = NULL;
3742 if (p->texture_reflection)
3743 R_FreeTexture(p->texture_reflection);
3744 p->texture_reflection = NULL;
3746 memset(&r_waterstate, 0, sizeof(r_waterstate));
3747 r_waterstate.texturewidth = texturewidth;
3748 r_waterstate.textureheight = textureheight;
3751 if (r_waterstate.texturewidth)
3753 r_waterstate.enabled = true;
3755 // when doing a reduced render (HDR) we want to use a smaller area
3756 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3757 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3759 // set up variables that will be used in shader setup
3760 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3761 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3762 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
3763 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
3766 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3767 r_waterstate.numwaterplanes = 0;
3770 void R_Water_AddWaterPlane(msurface_t *surface)
3772 int triangleindex, planeindex;
3778 r_waterstate_waterplane_t *p;
3779 texture_t *t = R_GetCurrentTexture(surface->texture);
3780 // just use the first triangle with a valid normal for any decisions
3781 VectorClear(normal);
3782 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3784 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3785 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3786 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3787 TriangleNormal(vert[0], vert[1], vert[2], normal);
3788 if (VectorLength2(normal) >= 0.001)
3792 VectorCopy(normal, plane.normal);
3793 VectorNormalize(plane.normal);
3794 plane.dist = DotProduct(vert[0], plane.normal);
3795 PlaneClassify(&plane);
3796 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3798 // skip backfaces (except if nocullface is set)
3799 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3801 VectorNegate(plane.normal, plane.normal);
3803 PlaneClassify(&plane);
3807 // find a matching plane if there is one
3808 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3809 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3811 if (planeindex >= r_waterstate.maxwaterplanes)
3812 return; // nothing we can do, out of planes
3814 // if this triangle does not fit any known plane rendered this frame, add one
3815 if (planeindex >= r_waterstate.numwaterplanes)
3817 // store the new plane
3818 r_waterstate.numwaterplanes++;
3820 // clear materialflags and pvs
3821 p->materialflags = 0;
3822 p->pvsvalid = false;
3824 // merge this surface's materialflags into the waterplane
3825 p->materialflags |= t->currentmaterialflags;
3826 // merge this surface's PVS into the waterplane
3827 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3828 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3829 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3831 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3836 static void R_Water_ProcessPlanes(void)
3838 r_refdef_view_t originalview;
3839 r_refdef_view_t myview;
3841 r_waterstate_waterplane_t *p;
3843 originalview = r_refdef.view;
3845 // make sure enough textures are allocated
3846 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3848 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3850 if (!p->texture_refraction)
3851 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);
3852 if (!p->texture_refraction)
3856 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3858 if (!p->texture_reflection)
3859 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);
3860 if (!p->texture_reflection)
3866 r_refdef.view = originalview;
3867 r_refdef.view.showdebug = false;
3868 r_refdef.view.width = r_waterstate.waterwidth;
3869 r_refdef.view.height = r_waterstate.waterheight;
3870 r_refdef.view.useclipplane = true;
3871 myview = r_refdef.view;
3872 r_waterstate.renderingscene = true;
3873 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3875 // render the normal view scene and copy into texture
3876 // (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)
3877 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3879 r_refdef.view = myview;
3880 r_refdef.view.clipplane = p->plane;
3881 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3882 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3883 PlaneClassify(&r_refdef.view.clipplane);
3885 R_ResetViewRendering3D();
3886 R_ClearScreen(r_refdef.fogenabled);
3890 // copy view into the screen texture
3891 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3892 GL_ActiveTexture(0);
3894 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
3897 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3899 r_refdef.view = myview;
3900 // render reflected scene and copy into texture
3901 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3902 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3903 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3904 r_refdef.view.clipplane = p->plane;
3905 // reverse the cullface settings for this render
3906 r_refdef.view.cullface_front = GL_FRONT;
3907 r_refdef.view.cullface_back = GL_BACK;
3908 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3910 r_refdef.view.usecustompvs = true;
3912 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3914 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3917 R_ResetViewRendering3D();
3918 R_ClearScreen(r_refdef.fogenabled);
3922 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3923 GL_ActiveTexture(0);
3925 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
3928 r_waterstate.renderingscene = false;
3929 r_refdef.view = originalview;
3930 R_ResetViewRendering3D();
3931 R_ClearScreen(r_refdef.fogenabled);
3935 r_refdef.view = originalview;
3936 r_waterstate.renderingscene = false;
3937 Cvar_SetValueQuick(&r_water, 0);
3938 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3942 void R_Bloom_StartFrame(void)
3944 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3946 // set bloomwidth and bloomheight to the bloom resolution that will be
3947 // used (often less than the screen resolution for faster rendering)
3948 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
3949 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
3950 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
3951 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
3952 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
3954 // calculate desired texture sizes
3955 if (gl_support_arb_texture_non_power_of_two)
3957 screentexturewidth = r_refdef.view.width;
3958 screentextureheight = r_refdef.view.height;
3959 bloomtexturewidth = r_bloomstate.bloomwidth;
3960 bloomtextureheight = r_bloomstate.bloomheight;
3964 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3965 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3966 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3967 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3970 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))
3972 Cvar_SetValueQuick(&r_hdr, 0);
3973 Cvar_SetValueQuick(&r_bloom, 0);
3974 Cvar_SetValueQuick(&r_motionblur, 0);
3975 Cvar_SetValueQuick(&r_damageblur, 0);
3978 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)))
3979 screentexturewidth = screentextureheight = 0;
3980 if (!r_hdr.integer && !r_bloom.integer)
3981 bloomtexturewidth = bloomtextureheight = 0;
3983 // allocate textures as needed
3984 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3986 if (r_bloomstate.texture_screen)
3987 R_FreeTexture(r_bloomstate.texture_screen);
3988 r_bloomstate.texture_screen = NULL;
3989 r_bloomstate.screentexturewidth = screentexturewidth;
3990 r_bloomstate.screentextureheight = screentextureheight;
3991 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3992 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);
3994 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3996 if (r_bloomstate.texture_bloom)
3997 R_FreeTexture(r_bloomstate.texture_bloom);
3998 r_bloomstate.texture_bloom = NULL;
3999 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4000 r_bloomstate.bloomtextureheight = bloomtextureheight;
4001 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4002 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);
4005 // when doing a reduced render (HDR) we want to use a smaller area
4006 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4007 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4008 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4009 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4010 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4012 // set up a texcoord array for the full resolution screen image
4013 // (we have to keep this around to copy back during final render)
4014 r_bloomstate.screentexcoord2f[0] = 0;
4015 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4016 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4017 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
4018 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
4019 r_bloomstate.screentexcoord2f[5] = 0;
4020 r_bloomstate.screentexcoord2f[6] = 0;
4021 r_bloomstate.screentexcoord2f[7] = 0;
4023 // set up a texcoord array for the reduced resolution bloom image
4024 // (which will be additive blended over the screen image)
4025 r_bloomstate.bloomtexcoord2f[0] = 0;
4026 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4027 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4028 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4029 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4030 r_bloomstate.bloomtexcoord2f[5] = 0;
4031 r_bloomstate.bloomtexcoord2f[6] = 0;
4032 r_bloomstate.bloomtexcoord2f[7] = 0;
4034 if (r_hdr.integer || r_bloom.integer)
4036 r_bloomstate.enabled = true;
4037 r_bloomstate.hdr = r_hdr.integer != 0;
4040 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);
4043 void R_Bloom_CopyBloomTexture(float colorscale)
4045 r_refdef.stats.bloom++;
4047 // scale down screen texture to the bloom texture size
4049 R_SetViewport(&r_bloomstate.viewport);
4050 GL_BlendFunc(GL_ONE, GL_ZERO);
4051 GL_Color(colorscale, colorscale, colorscale, 1);
4052 // TODO: optimize with multitexture or GLSL
4053 R_SetupGenericShader(true);
4054 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4055 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4056 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4057 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4059 // we now have a bloom image in the framebuffer
4060 // copy it into the bloom image texture for later processing
4061 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4062 GL_ActiveTexture(0);
4064 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4065 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4068 void R_Bloom_CopyHDRTexture(void)
4070 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4071 GL_ActiveTexture(0);
4073 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
4074 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4077 void R_Bloom_MakeTexture(void)
4080 float xoffset, yoffset, r, brighten;
4082 r_refdef.stats.bloom++;
4084 R_ResetViewRendering2D();
4085 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4086 R_Mesh_ColorPointer(NULL, 0, 0);
4087 R_SetupGenericShader(true);
4089 // we have a bloom image in the framebuffer
4091 R_SetViewport(&r_bloomstate.viewport);
4093 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4096 r = bound(0, r_bloom_colorexponent.value / x, 1);
4097 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4098 GL_Color(r, r, r, 1);
4099 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4100 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4101 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4102 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
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 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4112 brighten = r_bloom_brighten.value;
4114 brighten *= r_hdr_range.value;
4115 brighten = sqrt(brighten);
4117 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4118 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4119 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4121 for (dir = 0;dir < 2;dir++)
4123 // blend on at multiple vertical offsets to achieve a vertical blur
4124 // TODO: do offset blends using GLSL
4125 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4126 GL_BlendFunc(GL_ONE, GL_ZERO);
4127 for (x = -range;x <= range;x++)
4129 if (!dir){xoffset = 0;yoffset = x;}
4130 else {xoffset = x;yoffset = 0;}
4131 xoffset /= (float)r_bloomstate.bloomtexturewidth;
4132 yoffset /= (float)r_bloomstate.bloomtextureheight;
4133 // compute a texcoord array with the specified x and y offset
4134 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4135 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4136 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4137 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4138 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4139 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4140 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4141 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4142 // this r value looks like a 'dot' particle, fading sharply to
4143 // black at the edges
4144 // (probably not realistic but looks good enough)
4145 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4146 //r = brighten/(range*2+1);
4147 r = brighten / (range * 2 + 1);
4149 r *= (1 - x*x/(float)(range*range));
4150 GL_Color(r, r, r, 1);
4151 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4152 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4153 GL_BlendFunc(GL_ONE, GL_ONE);
4156 // copy the vertically blurred bloom view to a texture
4157 GL_ActiveTexture(0);
4159 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4160 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4163 // apply subtract last
4164 // (just like it would be in a GLSL shader)
4165 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4167 GL_BlendFunc(GL_ONE, GL_ZERO);
4168 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4169 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4170 GL_Color(1, 1, 1, 1);
4171 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4172 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4174 GL_BlendFunc(GL_ONE, GL_ONE);
4175 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4176 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4177 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4178 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4179 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4180 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4181 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4183 // copy the darkened bloom view to a texture
4184 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4185 GL_ActiveTexture(0);
4187 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4188 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4192 void R_HDR_RenderBloomTexture(void)
4194 int oldwidth, oldheight;
4195 float oldcolorscale;
4197 oldcolorscale = r_refdef.view.colorscale;
4198 oldwidth = r_refdef.view.width;
4199 oldheight = r_refdef.view.height;
4200 r_refdef.view.width = r_bloomstate.bloomwidth;
4201 r_refdef.view.height = r_bloomstate.bloomheight;
4203 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4204 // TODO: add exposure compensation features
4205 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4207 r_refdef.view.showdebug = false;
4208 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4210 R_ResetViewRendering3D();
4212 R_ClearScreen(r_refdef.fogenabled);
4213 if (r_timereport_active)
4214 R_TimeReport("HDRclear");
4217 if (r_timereport_active)
4218 R_TimeReport("visibility");
4220 // only do secondary renders with HDR if r_hdr is 2 or higher
4221 r_waterstate.numwaterplanes = 0;
4222 if (r_waterstate.enabled && r_hdr.integer >= 2)
4223 R_RenderWaterPlanes();
4225 r_refdef.view.showdebug = true;
4227 r_waterstate.numwaterplanes = 0;
4229 R_ResetViewRendering2D();
4231 R_Bloom_CopyHDRTexture();
4232 R_Bloom_MakeTexture();
4234 // restore the view settings
4235 r_refdef.view.width = oldwidth;
4236 r_refdef.view.height = oldheight;
4237 r_refdef.view.colorscale = oldcolorscale;
4239 R_ResetViewRendering3D();
4241 R_ClearScreen(r_refdef.fogenabled);
4242 if (r_timereport_active)
4243 R_TimeReport("viewclear");
4246 static void R_BlendView(void)
4248 if (r_bloomstate.texture_screen)
4250 // make sure the buffer is available
4251 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4253 R_ResetViewRendering2D();
4254 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4255 R_Mesh_ColorPointer(NULL, 0, 0);
4256 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4257 GL_ActiveTexture(0);CHECKGLERROR
4259 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4261 // declare variables
4263 static float avgspeed;
4265 speed = VectorLength(cl.movement_velocity);
4267 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4268 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4270 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4271 speed = bound(0, speed, 1);
4272 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4274 // calculate values into a standard alpha
4275 cl.motionbluralpha = 1 - exp(-
4277 (r_motionblur.value * speed / 80)
4279 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4282 max(0.0001, cl.time - cl.oldtime) // fps independent
4285 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4286 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4288 if (cl.motionbluralpha > 0)
4290 R_SetupGenericShader(true);
4291 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4292 GL_Color(1, 1, 1, cl.motionbluralpha);
4293 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4294 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4295 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4296 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4300 // copy view into the screen texture
4301 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
4302 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4305 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4307 unsigned int permutation =
4308 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4309 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4310 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4311 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4312 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4314 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4316 // render simple bloom effect
4317 // copy the screen and shrink it and darken it for the bloom process
4318 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4319 // make the bloom texture
4320 R_Bloom_MakeTexture();
4323 R_ResetViewRendering2D();
4324 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4325 R_Mesh_ColorPointer(NULL, 0, 0);
4326 GL_Color(1, 1, 1, 1);
4327 GL_BlendFunc(GL_ONE, GL_ZERO);
4328 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4329 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4330 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4331 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4332 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4333 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4334 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4335 if (r_glsl_permutation->loc_TintColor >= 0)
4336 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4337 if (r_glsl_permutation->loc_ClientTime >= 0)
4338 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4339 if (r_glsl_permutation->loc_PixelSize >= 0)
4340 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4341 if (r_glsl_permutation->loc_UserVec1 >= 0)
4343 float a=0, b=0, c=0, d=0;
4344 #if _MSC_VER >= 1400
4345 #define sscanf sscanf_s
4347 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4348 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4350 if (r_glsl_permutation->loc_UserVec2 >= 0)
4352 float a=0, b=0, c=0, d=0;
4353 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4354 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4356 if (r_glsl_permutation->loc_UserVec3 >= 0)
4358 float a=0, b=0, c=0, d=0;
4359 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4360 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4362 if (r_glsl_permutation->loc_UserVec4 >= 0)
4364 float a=0, b=0, c=0, d=0;
4365 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4366 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4368 if (r_glsl_permutation->loc_Saturation >= 0)
4369 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4370 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4371 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4377 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4379 // render high dynamic range bloom effect
4380 // the bloom texture was made earlier this render, so we just need to
4381 // blend it onto the screen...
4382 R_ResetViewRendering2D();
4383 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4384 R_Mesh_ColorPointer(NULL, 0, 0);
4385 R_SetupGenericShader(true);
4386 GL_Color(1, 1, 1, 1);
4387 GL_BlendFunc(GL_ONE, GL_ONE);
4388 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4389 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4390 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4391 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4393 else if (r_bloomstate.texture_bloom)
4395 // render simple bloom effect
4396 // copy the screen and shrink it and darken it for the bloom process
4397 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4398 // make the bloom texture
4399 R_Bloom_MakeTexture();
4400 // put the original screen image back in place and blend the bloom
4402 R_ResetViewRendering2D();
4403 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4404 R_Mesh_ColorPointer(NULL, 0, 0);
4405 GL_Color(1, 1, 1, 1);
4406 GL_BlendFunc(GL_ONE, GL_ZERO);
4407 // do both in one pass if possible
4408 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4409 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4410 if (r_textureunits.integer >= 2 && gl_combine.integer)
4412 R_SetupGenericTwoTextureShader(GL_ADD);
4413 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4414 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4418 R_SetupGenericShader(true);
4419 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4420 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4421 // now blend on the bloom texture
4422 GL_BlendFunc(GL_ONE, GL_ONE);
4423 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4424 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4426 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4427 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4429 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4431 // apply a color tint to the whole view
4432 R_ResetViewRendering2D();
4433 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4434 R_Mesh_ColorPointer(NULL, 0, 0);
4435 R_SetupGenericShader(false);
4436 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4437 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4438 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4442 matrix4x4_t r_waterscrollmatrix;
4444 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4446 if (r_refdef.fog_density)
4448 r_refdef.fogcolor[0] = r_refdef.fog_red;
4449 r_refdef.fogcolor[1] = r_refdef.fog_green;
4450 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4454 VectorCopy(r_refdef.fogcolor, fogvec);
4455 // color.rgb *= ContrastBoost * SceneBrightness;
4456 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4457 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4458 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4459 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4464 void R_UpdateVariables(void)
4468 r_refdef.scene.ambient = r_ambient.value;
4470 r_refdef.farclip = 4096;
4471 if (r_refdef.scene.worldmodel)
4472 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
4473 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4475 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4476 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4477 r_refdef.polygonfactor = 0;
4478 r_refdef.polygonoffset = 0;
4479 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4480 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4482 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4483 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4484 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4485 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4486 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4487 if (r_showsurfaces.integer)
4489 r_refdef.scene.rtworld = false;
4490 r_refdef.scene.rtworldshadows = false;
4491 r_refdef.scene.rtdlight = false;
4492 r_refdef.scene.rtdlightshadows = false;
4493 r_refdef.lightmapintensity = 0;
4496 if (gamemode == GAME_NEHAHRA)
4498 if (gl_fogenable.integer)
4500 r_refdef.oldgl_fogenable = true;
4501 r_refdef.fog_density = gl_fogdensity.value;
4502 r_refdef.fog_red = gl_fogred.value;
4503 r_refdef.fog_green = gl_foggreen.value;
4504 r_refdef.fog_blue = gl_fogblue.value;
4505 r_refdef.fog_alpha = 1;
4506 r_refdef.fog_start = 0;
4507 r_refdef.fog_end = gl_skyclip.value;
4509 else if (r_refdef.oldgl_fogenable)
4511 r_refdef.oldgl_fogenable = false;
4512 r_refdef.fog_density = 0;
4513 r_refdef.fog_red = 0;
4514 r_refdef.fog_green = 0;
4515 r_refdef.fog_blue = 0;
4516 r_refdef.fog_alpha = 0;
4517 r_refdef.fog_start = 0;
4518 r_refdef.fog_end = 0;
4522 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4523 r_refdef.fog_start = max(0, r_refdef.fog_start);
4524 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4526 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4528 if (r_refdef.fog_density && r_drawfog.integer)
4530 r_refdef.fogenabled = true;
4531 // this is the point where the fog reaches 0.9986 alpha, which we
4532 // consider a good enough cutoff point for the texture
4533 // (0.9986 * 256 == 255.6)
4534 if (r_fog_exp2.integer)
4535 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4537 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4538 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4539 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4540 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4541 // fog color was already set
4542 // update the fog texture
4543 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)
4544 R_BuildFogTexture();
4547 r_refdef.fogenabled = false;
4549 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4551 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4553 // build GLSL gamma texture
4554 #define RAMPWIDTH 256
4555 unsigned short ramp[RAMPWIDTH * 3];
4556 unsigned char rampbgr[RAMPWIDTH][4];
4559 r_texture_gammaramps_serial = vid_gammatables_serial;
4561 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4562 for(i = 0; i < RAMPWIDTH; ++i)
4564 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4565 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4566 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4569 if (r_texture_gammaramps)
4571 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4575 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);
4581 // remove GLSL gamma texture
4585 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4586 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4592 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4593 if( scenetype != r_currentscenetype ) {
4594 // store the old scenetype
4595 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4596 r_currentscenetype = scenetype;
4597 // move in the new scene
4598 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4607 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4609 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4610 if( scenetype == r_currentscenetype ) {
4611 return &r_refdef.scene;
4613 return &r_scenes_store[ scenetype ];
4622 void R_RenderView(void)
4624 if (r_timereport_active)
4625 R_TimeReport("start");
4626 r_frame++; // used only by R_GetCurrentTexture
4627 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4629 R_AnimCache_NewFrame();
4631 if (r_refdef.view.isoverlay)
4633 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4634 GL_Clear( GL_DEPTH_BUFFER_BIT );
4635 R_TimeReport("depthclear");
4637 r_refdef.view.showdebug = false;
4639 r_waterstate.enabled = false;
4640 r_waterstate.numwaterplanes = 0;
4648 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4649 return; //Host_Error ("R_RenderView: NULL worldmodel");
4651 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4653 // break apart the view matrix into vectors for various purposes
4654 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4655 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4656 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4657 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4658 // make an inverted copy of the view matrix for tracking sprites
4659 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4661 R_Shadow_UpdateWorldLightSelection();
4663 R_Bloom_StartFrame();
4664 R_Water_StartFrame();
4667 if (r_timereport_active)
4668 R_TimeReport("viewsetup");
4670 R_ResetViewRendering3D();
4672 if (r_refdef.view.clear || r_refdef.fogenabled)
4674 R_ClearScreen(r_refdef.fogenabled);
4675 if (r_timereport_active)
4676 R_TimeReport("viewclear");
4678 r_refdef.view.clear = true;
4680 // this produces a bloom texture to be used in R_BlendView() later
4682 R_HDR_RenderBloomTexture();
4684 r_refdef.view.showdebug = true;
4687 if (r_timereport_active)
4688 R_TimeReport("visibility");
4690 r_waterstate.numwaterplanes = 0;
4691 if (r_waterstate.enabled)
4692 R_RenderWaterPlanes();
4695 r_waterstate.numwaterplanes = 0;
4698 if (r_timereport_active)
4699 R_TimeReport("blendview");
4701 GL_Scissor(0, 0, vid.width, vid.height);
4702 GL_ScissorTest(false);
4706 void R_RenderWaterPlanes(void)
4708 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4710 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4711 if (r_timereport_active)
4712 R_TimeReport("waterworld");
4715 // don't let sound skip if going slow
4716 if (r_refdef.scene.extraupdate)
4719 R_DrawModelsAddWaterPlanes();
4720 if (r_timereport_active)
4721 R_TimeReport("watermodels");
4723 if (r_waterstate.numwaterplanes)
4725 R_Water_ProcessPlanes();
4726 if (r_timereport_active)
4727 R_TimeReport("waterscenes");
4731 extern void R_DrawLightningBeams (void);
4732 extern void VM_CL_AddPolygonsToMeshQueue (void);
4733 extern void R_DrawPortals (void);
4734 extern cvar_t cl_locs_show;
4735 static void R_DrawLocs(void);
4736 static void R_DrawEntityBBoxes(void);
4737 void R_RenderScene(void)
4739 r_refdef.stats.renders++;
4743 // don't let sound skip if going slow
4744 if (r_refdef.scene.extraupdate)
4747 R_MeshQueue_BeginScene();
4751 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);
4753 if (cl.csqc_vidvars.drawworld)
4755 // don't let sound skip if going slow
4756 if (r_refdef.scene.extraupdate)
4759 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4761 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4762 if (r_timereport_active)
4763 R_TimeReport("worldsky");
4766 if (R_DrawBrushModelsSky() && r_timereport_active)
4767 R_TimeReport("bmodelsky");
4770 R_AnimCache_CacheVisibleEntities();
4772 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4774 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4775 if (r_timereport_active)
4776 R_TimeReport("worlddepth");
4778 if (r_depthfirst.integer >= 2)
4780 R_DrawModelsDepth();
4781 if (r_timereport_active)
4782 R_TimeReport("modeldepth");
4785 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4787 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4788 if (r_timereport_active)
4789 R_TimeReport("world");
4792 // don't let sound skip if going slow
4793 if (r_refdef.scene.extraupdate)
4797 if (r_timereport_active)
4798 R_TimeReport("models");
4800 // don't let sound skip if going slow
4801 if (r_refdef.scene.extraupdate)
4804 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4806 R_DrawModelShadows();
4807 R_ResetViewRendering3D();
4808 // don't let sound skip if going slow
4809 if (r_refdef.scene.extraupdate)
4813 R_ShadowVolumeLighting(false);
4814 if (r_timereport_active)
4815 R_TimeReport("rtlights");
4817 // don't let sound skip if going slow
4818 if (r_refdef.scene.extraupdate)
4821 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4823 R_DrawModelShadows();
4824 R_ResetViewRendering3D();
4825 // don't let sound skip if going slow
4826 if (r_refdef.scene.extraupdate)
4830 if (cl.csqc_vidvars.drawworld)
4832 R_DrawLightningBeams();
4833 if (r_timereport_active)
4834 R_TimeReport("lightning");
4837 if (r_timereport_active)
4838 R_TimeReport("decals");
4841 if (r_timereport_active)
4842 R_TimeReport("particles");
4845 if (r_timereport_active)
4846 R_TimeReport("explosions");
4849 R_SetupGenericShader(true);
4850 VM_CL_AddPolygonsToMeshQueue();
4852 if (r_refdef.view.showdebug)
4854 if (cl_locs_show.integer)
4857 if (r_timereport_active)
4858 R_TimeReport("showlocs");
4861 if (r_drawportals.integer)
4864 if (r_timereport_active)
4865 R_TimeReport("portals");
4868 if (r_showbboxes.value > 0)
4870 R_DrawEntityBBoxes();
4871 if (r_timereport_active)
4872 R_TimeReport("bboxes");
4876 R_SetupGenericShader(true);
4877 R_MeshQueue_RenderTransparent();
4878 if (r_timereport_active)
4879 R_TimeReport("drawtrans");
4881 R_SetupGenericShader(true);
4883 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))
4885 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4886 if (r_timereport_active)
4887 R_TimeReport("worlddebug");
4888 R_DrawModelsDebug();
4889 if (r_timereport_active)
4890 R_TimeReport("modeldebug");
4893 R_SetupGenericShader(true);
4895 if (cl.csqc_vidvars.drawworld)
4898 if (r_timereport_active)
4899 R_TimeReport("coronas");
4902 // don't let sound skip if going slow
4903 if (r_refdef.scene.extraupdate)
4906 R_ResetViewRendering2D();
4909 static const unsigned short bboxelements[36] =
4919 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4922 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4923 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4924 GL_DepthMask(false);
4925 GL_DepthRange(0, 1);
4926 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4927 R_Mesh_Matrix(&identitymatrix);
4928 R_Mesh_ResetTextureState();
4930 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4931 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4932 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4933 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4934 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4935 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4936 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4937 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4938 R_FillColors(color4f, 8, cr, cg, cb, ca);
4939 if (r_refdef.fogenabled)
4941 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4943 f1 = FogPoint_World(v);
4945 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4946 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4947 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4950 R_Mesh_VertexPointer(vertex3f, 0, 0);
4951 R_Mesh_ColorPointer(color4f, 0, 0);
4952 R_Mesh_ResetTextureState();
4953 R_SetupGenericShader(false);
4954 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4957 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4961 prvm_edict_t *edict;
4962 prvm_prog_t *prog_save = prog;
4964 // this function draws bounding boxes of server entities
4968 GL_CullFace(GL_NONE);
4969 R_SetupGenericShader(false);
4973 for (i = 0;i < numsurfaces;i++)
4975 edict = PRVM_EDICT_NUM(surfacelist[i]);
4976 switch ((int)edict->fields.server->solid)
4978 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4979 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4980 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4981 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4982 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4983 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4985 color[3] *= r_showbboxes.value;
4986 color[3] = bound(0, color[3], 1);
4987 GL_DepthTest(!r_showdisabledepthtest.integer);
4988 GL_CullFace(r_refdef.view.cullface_front);
4989 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4995 static void R_DrawEntityBBoxes(void)
4998 prvm_edict_t *edict;
5000 prvm_prog_t *prog_save = prog;
5002 // this function draws bounding boxes of server entities
5008 for (i = 0;i < prog->num_edicts;i++)
5010 edict = PRVM_EDICT_NUM(i);
5011 if (edict->priv.server->free)
5013 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5014 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5016 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5018 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5019 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5025 unsigned short nomodelelements[24] =
5037 float nomodelvertex3f[6*3] =
5047 float nomodelcolor4f[6*4] =
5049 0.0f, 0.0f, 0.5f, 1.0f,
5050 0.0f, 0.0f, 0.5f, 1.0f,
5051 0.0f, 0.5f, 0.0f, 1.0f,
5052 0.0f, 0.5f, 0.0f, 1.0f,
5053 0.5f, 0.0f, 0.0f, 1.0f,
5054 0.5f, 0.0f, 0.0f, 1.0f
5057 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5062 // this is only called once per entity so numsurfaces is always 1, and
5063 // surfacelist is always {0}, so this code does not handle batches
5064 R_Mesh_Matrix(&ent->matrix);
5066 if (ent->flags & EF_ADDITIVE)
5068 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5069 GL_DepthMask(false);
5071 else if (ent->alpha < 1)
5073 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5074 GL_DepthMask(false);
5078 GL_BlendFunc(GL_ONE, GL_ZERO);
5081 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5082 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5083 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
5084 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5085 R_SetupGenericShader(false);
5086 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
5087 if (r_refdef.fogenabled)
5090 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5091 R_Mesh_ColorPointer(color4f, 0, 0);
5092 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5093 f1 = FogPoint_World(org);
5095 for (i = 0, c = color4f;i < 6;i++, c += 4)
5097 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5098 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5099 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5103 else if (ent->alpha != 1)
5105 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5106 R_Mesh_ColorPointer(color4f, 0, 0);
5107 for (i = 0, c = color4f;i < 6;i++, c += 4)
5111 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
5112 R_Mesh_ResetTextureState();
5113 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
5116 void R_DrawNoModel(entity_render_t *ent)
5119 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5120 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
5121 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5123 // R_DrawNoModelCallback(ent, 0);
5126 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5128 vec3_t right1, right2, diff, normal;
5130 VectorSubtract (org2, org1, normal);
5132 // calculate 'right' vector for start
5133 VectorSubtract (r_refdef.view.origin, org1, diff);
5134 CrossProduct (normal, diff, right1);
5135 VectorNormalize (right1);
5137 // calculate 'right' vector for end
5138 VectorSubtract (r_refdef.view.origin, org2, diff);
5139 CrossProduct (normal, diff, right2);
5140 VectorNormalize (right2);
5142 vert[ 0] = org1[0] + width * right1[0];
5143 vert[ 1] = org1[1] + width * right1[1];
5144 vert[ 2] = org1[2] + width * right1[2];
5145 vert[ 3] = org1[0] - width * right1[0];
5146 vert[ 4] = org1[1] - width * right1[1];
5147 vert[ 5] = org1[2] - width * right1[2];
5148 vert[ 6] = org2[0] - width * right2[0];
5149 vert[ 7] = org2[1] - width * right2[1];
5150 vert[ 8] = org2[2] - width * right2[2];
5151 vert[ 9] = org2[0] + width * right2[0];
5152 vert[10] = org2[1] + width * right2[1];
5153 vert[11] = org2[2] + width * right2[2];
5156 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
5158 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)
5160 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
5164 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
5165 fog = FogPoint_World(origin);
5167 R_Mesh_Matrix(&identitymatrix);
5168 GL_BlendFunc(blendfunc1, blendfunc2);
5170 GL_CullFace(GL_NONE);
5172 GL_DepthMask(false);
5173 GL_DepthRange(0, depthshort ? 0.0625 : 1);
5174 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5175 GL_DepthTest(!depthdisable);
5177 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5178 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5179 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5180 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5181 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5182 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5183 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5184 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5185 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5186 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5187 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5188 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5190 R_Mesh_VertexPointer(vertex3f, 0, 0);
5191 R_Mesh_ColorPointer(NULL, 0, 0);
5192 R_Mesh_ResetTextureState();
5193 R_SetupGenericShader(true);
5194 R_Mesh_TexBind(0, R_GetTexture(texture));
5195 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
5196 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
5197 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
5198 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5200 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
5202 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
5203 GL_BlendFunc(blendfunc1, GL_ONE);
5205 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
5206 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5210 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5215 VectorSet(v, x, y, z);
5216 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5217 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5219 if (i == mesh->numvertices)
5221 if (mesh->numvertices < mesh->maxvertices)
5223 VectorCopy(v, vertex3f);
5224 mesh->numvertices++;
5226 return mesh->numvertices;
5232 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5236 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5237 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5238 e = mesh->element3i + mesh->numtriangles * 3;
5239 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5241 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5242 if (mesh->numtriangles < mesh->maxtriangles)
5247 mesh->numtriangles++;
5249 element[1] = element[2];
5253 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5257 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5258 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5259 e = mesh->element3i + mesh->numtriangles * 3;
5260 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5262 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5263 if (mesh->numtriangles < mesh->maxtriangles)
5268 mesh->numtriangles++;
5270 element[1] = element[2];
5274 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5275 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5277 int planenum, planenum2;
5280 mplane_t *plane, *plane2;
5282 double temppoints[2][256*3];
5283 // figure out how large a bounding box we need to properly compute this brush
5285 for (w = 0;w < numplanes;w++)
5286 maxdist = max(maxdist, planes[w].dist);
5287 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5288 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5289 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5293 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5294 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5296 if (planenum2 == planenum)
5298 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);
5301 if (tempnumpoints < 3)
5303 // generate elements forming a triangle fan for this polygon
5304 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5308 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)
5310 texturelayer_t *layer;
5311 layer = t->currentlayers + t->currentnumlayers++;
5313 layer->depthmask = depthmask;
5314 layer->blendfunc1 = blendfunc1;
5315 layer->blendfunc2 = blendfunc2;
5316 layer->texture = texture;
5317 layer->texmatrix = *matrix;
5318 layer->color[0] = r * r_refdef.view.colorscale;
5319 layer->color[1] = g * r_refdef.view.colorscale;
5320 layer->color[2] = b * r_refdef.view.colorscale;
5321 layer->color[3] = a;
5324 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5327 index = parms[2] + r_refdef.scene.time * parms[3];
5328 index -= floor(index);
5332 case Q3WAVEFUNC_NONE:
5333 case Q3WAVEFUNC_NOISE:
5334 case Q3WAVEFUNC_COUNT:
5337 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5338 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5339 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5340 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5341 case Q3WAVEFUNC_TRIANGLE:
5343 f = index - floor(index);
5354 return (float)(parms[0] + parms[1] * f);
5357 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5362 matrix4x4_t matrix, temp;
5363 switch(tcmod->tcmod)
5367 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5368 matrix = r_waterscrollmatrix;
5370 matrix = identitymatrix;
5372 case Q3TCMOD_ENTITYTRANSLATE:
5373 // this is used in Q3 to allow the gamecode to control texcoord
5374 // scrolling on the entity, which is not supported in darkplaces yet.
5375 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5377 case Q3TCMOD_ROTATE:
5378 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5379 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5380 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5383 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5385 case Q3TCMOD_SCROLL:
5386 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5388 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5389 w = (int) tcmod->parms[0];
5390 h = (int) tcmod->parms[1];
5391 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5393 idx = (int) floor(f * w * h);
5394 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5396 case Q3TCMOD_STRETCH:
5397 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5398 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5400 case Q3TCMOD_TRANSFORM:
5401 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5402 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5403 VectorSet(tcmat + 6, 0 , 0 , 1);
5404 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5405 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5407 case Q3TCMOD_TURBULENT:
5408 // this is handled in the RSurf_PrepareVertices function
5409 matrix = identitymatrix;
5413 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5416 texture_t *R_GetCurrentTexture(texture_t *t)
5419 const entity_render_t *ent = rsurface.entity;
5420 dp_model_t *model = ent->model;
5421 q3shaderinfo_layer_tcmod_t *tcmod;
5423 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5424 return t->currentframe;
5425 t->update_lastrenderframe = r_frame;
5426 t->update_lastrenderentity = (void *)ent;
5428 // switch to an alternate material if this is a q1bsp animated material
5430 texture_t *texture = t;
5431 int s = ent->skinnum;
5432 if ((unsigned int)s >= (unsigned int)model->numskins)
5434 if (model->skinscenes)
5436 if (model->skinscenes[s].framecount > 1)
5437 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5439 s = model->skinscenes[s].firstframe;
5442 t = t + s * model->num_surfaces;
5445 // use an alternate animation if the entity's frame is not 0,
5446 // and only if the texture has an alternate animation
5447 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
5448 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5450 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5452 texture->currentframe = t;
5455 // update currentskinframe to be a qw skin or animation frame
5456 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"))
5458 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
5460 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
5461 if (developer_loading.integer)
5462 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
5463 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);
5465 t->currentskinframe = r_qwskincache_skinframe[i];
5466 if (t->currentskinframe == NULL)
5467 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5469 else if (t->numskinframes >= 2)
5470 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5471 if (t->backgroundnumskinframes >= 2)
5472 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
5474 t->currentmaterialflags = t->basematerialflags;
5475 t->currentalpha = ent->alpha;
5476 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5477 t->currentalpha *= r_wateralpha.value;
5478 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5479 t->currentalpha *= t->r_water_wateralpha;
5480 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5481 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5482 if (!(ent->flags & RENDER_LIGHT))
5483 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5484 else if (rsurface.modeltexcoordlightmap2f == NULL)
5486 // pick a model lighting mode
5487 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
5488 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5490 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5492 if (ent->effects & EF_ADDITIVE)
5493 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5494 else if (t->currentalpha < 1)
5495 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5496 if (ent->effects & EF_DOUBLESIDED)
5497 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5498 if (ent->effects & EF_NODEPTHTEST)
5499 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5500 if (ent->flags & RENDER_VIEWMODEL)
5501 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5502 if (t->backgroundnumskinframes)
5503 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5504 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5506 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5507 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5510 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5512 // there is no tcmod
5513 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5515 t->currenttexmatrix = r_waterscrollmatrix;
5516 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5520 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5521 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5524 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5525 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5526 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5527 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5529 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5530 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5531 t->glosstexture = r_texture_black;
5532 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5533 t->backgroundglosstexture = r_texture_black;
5534 t->specularpower = r_shadow_glossexponent.value;
5535 // TODO: store reference values for these in the texture?
5536 t->specularscale = 0;
5537 if (r_shadow_gloss.integer > 0)
5539 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5541 if (r_shadow_glossintensity.value > 0)
5543 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5544 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5545 t->specularscale = r_shadow_glossintensity.value;
5548 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5550 t->glosstexture = r_texture_white;
5551 t->backgroundglosstexture = r_texture_white;
5552 t->specularscale = r_shadow_gloss2intensity.value;
5553 t->specularpower = r_shadow_gloss2exponent.value;
5556 t->specularscale *= t->specularscalemod;
5557 t->specularpower *= t->specularpowermod;
5559 // lightmaps mode looks bad with dlights using actual texturing, so turn
5560 // off the colormap and glossmap, but leave the normalmap on as it still
5561 // accurately represents the shading involved
5562 if (gl_lightmaps.integer)
5564 t->basetexture = r_texture_grey128;
5565 t->backgroundbasetexture = NULL;
5566 t->specularscale = 0;
5567 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5570 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5571 VectorClear(t->dlightcolor);
5572 t->currentnumlayers = 0;
5573 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5576 int blendfunc1, blendfunc2;
5578 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5580 blendfunc1 = GL_SRC_ALPHA;
5581 blendfunc2 = GL_ONE;
5583 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5585 blendfunc1 = GL_SRC_ALPHA;
5586 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5588 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5590 blendfunc1 = t->customblendfunc[0];
5591 blendfunc2 = t->customblendfunc[1];
5595 blendfunc1 = GL_ONE;
5596 blendfunc2 = GL_ZERO;
5598 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5599 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5600 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5601 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5603 // fullbright is not affected by r_refdef.lightmapintensity
5604 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]);
5605 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5606 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]);
5607 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5608 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]);
5612 vec3_t ambientcolor;
5614 // set the color tint used for lights affecting this surface
5615 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5617 // q3bsp has no lightmap updates, so the lightstylevalue that
5618 // would normally be baked into the lightmap must be
5619 // applied to the color
5620 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5621 if (ent->model->type == mod_brushq3)
5622 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5623 colorscale *= r_refdef.lightmapintensity;
5624 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5625 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5626 // basic lit geometry
5627 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]);
5628 // add pants/shirt if needed
5629 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5630 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]);
5631 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5632 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]);
5633 // now add ambient passes if needed
5634 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5636 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]);
5637 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5638 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]);
5639 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5640 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]);
5643 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5644 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]);
5645 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5647 // if this is opaque use alpha blend which will darken the earlier
5650 // if this is an alpha blended material, all the earlier passes
5651 // were darkened by fog already, so we only need to add the fog
5652 // color ontop through the fog mask texture
5654 // if this is an additive blended material, all the earlier passes
5655 // were darkened by fog already, and we should not add fog color
5656 // (because the background was not darkened, there is no fog color
5657 // that was lost behind it).
5658 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]);
5662 return t->currentframe;
5665 rsurfacestate_t rsurface;
5667 void R_Mesh_ResizeArrays(int newvertices)
5670 if (rsurface.array_size >= newvertices)
5672 if (rsurface.array_modelvertex3f)
5673 Mem_Free(rsurface.array_modelvertex3f);
5674 rsurface.array_size = (newvertices + 1023) & ~1023;
5675 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5676 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5677 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5678 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5679 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5680 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5681 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5682 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5683 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5684 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5685 rsurface.array_color4f = base + rsurface.array_size * 27;
5686 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5689 void RSurf_ActiveWorldEntity(void)
5691 dp_model_t *model = r_refdef.scene.worldmodel;
5692 //if (rsurface.entity == r_refdef.scene.worldentity)
5694 rsurface.entity = r_refdef.scene.worldentity;
5695 if (rsurface.array_size < model->surfmesh.num_vertices)
5696 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5697 rsurface.matrix = identitymatrix;
5698 rsurface.inversematrix = identitymatrix;
5699 R_Mesh_Matrix(&identitymatrix);
5700 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5701 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5702 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5703 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5704 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5705 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5706 VectorSet(rsurface.glowmod, 1, 1, 1);
5707 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5708 rsurface.frameblend[0].lerp = 1;
5709 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5710 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5711 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5712 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5713 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5714 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5715 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5716 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5717 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5718 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5719 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5720 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5721 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5722 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5723 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5724 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5725 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5726 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5727 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5728 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5729 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5730 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5731 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5732 rsurface.modelelement3i = model->surfmesh.data_element3i;
5733 rsurface.modelelement3s = model->surfmesh.data_element3s;
5734 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5735 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5736 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5737 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5738 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5739 rsurface.modelsurfaces = model->data_surfaces;
5740 rsurface.generatedvertex = false;
5741 rsurface.vertex3f = rsurface.modelvertex3f;
5742 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5743 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5744 rsurface.svector3f = rsurface.modelsvector3f;
5745 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5746 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5747 rsurface.tvector3f = rsurface.modeltvector3f;
5748 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5749 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5750 rsurface.normal3f = rsurface.modelnormal3f;
5751 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5752 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5753 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5756 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5758 dp_model_t *model = ent->model;
5759 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5761 rsurface.entity = (entity_render_t *)ent;
5762 if (rsurface.array_size < model->surfmesh.num_vertices)
5763 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5764 rsurface.matrix = ent->matrix;
5765 rsurface.inversematrix = ent->inversematrix;
5766 R_Mesh_Matrix(&rsurface.matrix);
5767 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5768 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5769 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5770 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5771 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5772 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5773 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5774 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5775 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5776 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5777 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5778 VectorCopy(ent->glowmod, rsurface.glowmod);
5779 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5780 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5781 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5782 if (ent->model->brush.submodel)
5784 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5785 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5787 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5789 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5791 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5792 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5793 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5794 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5796 else if (wanttangents)
5798 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5799 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5800 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5801 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5802 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5804 else if (wantnormals)
5806 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5807 rsurface.modelsvector3f = NULL;
5808 rsurface.modeltvector3f = NULL;
5809 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5810 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5814 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5815 rsurface.modelsvector3f = NULL;
5816 rsurface.modeltvector3f = NULL;
5817 rsurface.modelnormal3f = NULL;
5818 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5820 rsurface.modelvertex3f_bufferobject = 0;
5821 rsurface.modelvertex3f_bufferoffset = 0;
5822 rsurface.modelsvector3f_bufferobject = 0;
5823 rsurface.modelsvector3f_bufferoffset = 0;
5824 rsurface.modeltvector3f_bufferobject = 0;
5825 rsurface.modeltvector3f_bufferoffset = 0;
5826 rsurface.modelnormal3f_bufferobject = 0;
5827 rsurface.modelnormal3f_bufferoffset = 0;
5828 rsurface.generatedvertex = true;
5832 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5833 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5834 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5835 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5836 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5837 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5838 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5839 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5840 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5841 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5842 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5843 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5844 rsurface.generatedvertex = false;
5846 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5847 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5848 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5849 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5850 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5851 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5852 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5853 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5854 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5855 rsurface.modelelement3i = model->surfmesh.data_element3i;
5856 rsurface.modelelement3s = model->surfmesh.data_element3s;
5857 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5858 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5859 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5860 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5861 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5862 rsurface.modelsurfaces = model->data_surfaces;
5863 rsurface.vertex3f = rsurface.modelvertex3f;
5864 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5865 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5866 rsurface.svector3f = rsurface.modelsvector3f;
5867 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5868 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5869 rsurface.tvector3f = rsurface.modeltvector3f;
5870 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5871 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5872 rsurface.normal3f = rsurface.modelnormal3f;
5873 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5874 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5875 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5878 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5879 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5882 int texturesurfaceindex;
5887 const float *v1, *in_tc;
5889 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5891 q3shaderinfo_deform_t *deform;
5892 // 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
5893 if (rsurface.generatedvertex)
5895 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5896 generatenormals = true;
5897 for (i = 0;i < Q3MAXDEFORMS;i++)
5899 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5901 generatetangents = true;
5902 generatenormals = true;
5904 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5905 generatenormals = true;
5907 if (generatenormals && !rsurface.modelnormal3f)
5909 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5910 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5911 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5912 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
5914 if (generatetangents && !rsurface.modelsvector3f)
5916 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5917 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5918 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5919 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5920 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5921 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5922 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);
5925 rsurface.vertex3f = rsurface.modelvertex3f;
5926 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5927 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5928 rsurface.svector3f = rsurface.modelsvector3f;
5929 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5930 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5931 rsurface.tvector3f = rsurface.modeltvector3f;
5932 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5933 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5934 rsurface.normal3f = rsurface.modelnormal3f;
5935 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5936 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5937 // if vertices are deformed (sprite flares and things in maps, possibly
5938 // water waves, bulges and other deformations), generate them into
5939 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5940 // (may be static model data or generated data for an animated model, or
5941 // the previous deform pass)
5942 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5944 switch (deform->deform)
5947 case Q3DEFORM_PROJECTIONSHADOW:
5948 case Q3DEFORM_TEXT0:
5949 case Q3DEFORM_TEXT1:
5950 case Q3DEFORM_TEXT2:
5951 case Q3DEFORM_TEXT3:
5952 case Q3DEFORM_TEXT4:
5953 case Q3DEFORM_TEXT5:
5954 case Q3DEFORM_TEXT6:
5955 case Q3DEFORM_TEXT7:
5958 case Q3DEFORM_AUTOSPRITE:
5959 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5960 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5961 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5962 VectorNormalize(newforward);
5963 VectorNormalize(newright);
5964 VectorNormalize(newup);
5965 // make deformed versions of only the model vertices used by the specified surfaces
5966 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5968 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5969 // a single autosprite surface can contain multiple sprites...
5970 for (j = 0;j < surface->num_vertices - 3;j += 4)
5972 VectorClear(center);
5973 for (i = 0;i < 4;i++)
5974 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5975 VectorScale(center, 0.25f, center);
5976 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5977 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5978 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5979 for (i = 0;i < 4;i++)
5981 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5982 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5985 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);
5986 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);
5988 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5989 rsurface.vertex3f_bufferobject = 0;
5990 rsurface.vertex3f_bufferoffset = 0;
5991 rsurface.svector3f = rsurface.array_deformedsvector3f;
5992 rsurface.svector3f_bufferobject = 0;
5993 rsurface.svector3f_bufferoffset = 0;
5994 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5995 rsurface.tvector3f_bufferobject = 0;
5996 rsurface.tvector3f_bufferoffset = 0;
5997 rsurface.normal3f = rsurface.array_deformednormal3f;
5998 rsurface.normal3f_bufferobject = 0;
5999 rsurface.normal3f_bufferoffset = 0;
6001 case Q3DEFORM_AUTOSPRITE2:
6002 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6003 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6004 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6005 VectorNormalize(newforward);
6006 VectorNormalize(newright);
6007 VectorNormalize(newup);
6008 // make deformed versions of only the model vertices used by the specified surfaces
6009 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6011 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6012 const float *v1, *v2;
6022 memset(shortest, 0, sizeof(shortest));
6023 // a single autosprite surface can contain multiple sprites...
6024 for (j = 0;j < surface->num_vertices - 3;j += 4)
6026 VectorClear(center);
6027 for (i = 0;i < 4;i++)
6028 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6029 VectorScale(center, 0.25f, center);
6030 // find the two shortest edges, then use them to define the
6031 // axis vectors for rotating around the central axis
6032 for (i = 0;i < 6;i++)
6034 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6035 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6037 Debug_PolygonBegin(NULL, 0);
6038 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6039 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);
6040 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6043 l = VectorDistance2(v1, v2);
6044 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6046 l += (1.0f / 1024.0f);
6047 if (shortest[0].length2 > l || i == 0)
6049 shortest[1] = shortest[0];
6050 shortest[0].length2 = l;
6051 shortest[0].v1 = v1;
6052 shortest[0].v2 = v2;
6054 else if (shortest[1].length2 > l || i == 1)
6056 shortest[1].length2 = l;
6057 shortest[1].v1 = v1;
6058 shortest[1].v2 = v2;
6061 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6062 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6064 Debug_PolygonBegin(NULL, 0);
6065 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6066 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);
6067 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6070 // this calculates the right vector from the shortest edge
6071 // and the up vector from the edge midpoints
6072 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6073 VectorNormalize(right);
6074 VectorSubtract(end, start, up);
6075 VectorNormalize(up);
6076 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6077 VectorSubtract(rsurface.modelorg, center, forward);
6078 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6079 VectorNegate(forward, forward);
6080 VectorReflect(forward, 0, up, forward);
6081 VectorNormalize(forward);
6082 CrossProduct(up, forward, newright);
6083 VectorNormalize(newright);
6085 Debug_PolygonBegin(NULL, 0);
6086 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);
6087 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6088 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6092 Debug_PolygonBegin(NULL, 0);
6093 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6094 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6095 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
6098 // rotate the quad around the up axis vector, this is made
6099 // especially easy by the fact we know the quad is flat,
6100 // so we only have to subtract the center position and
6101 // measure distance along the right vector, and then
6102 // multiply that by the newright vector and add back the
6104 // we also need to subtract the old position to undo the
6105 // displacement from the center, which we do with a
6106 // DotProduct, the subtraction/addition of center is also
6107 // optimized into DotProducts here
6108 l = DotProduct(right, center);
6109 for (i = 0;i < 4;i++)
6111 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6112 f = DotProduct(right, v1) - l;
6113 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6116 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);
6117 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);
6119 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6120 rsurface.vertex3f_bufferobject = 0;
6121 rsurface.vertex3f_bufferoffset = 0;
6122 rsurface.svector3f = rsurface.array_deformedsvector3f;
6123 rsurface.svector3f_bufferobject = 0;
6124 rsurface.svector3f_bufferoffset = 0;
6125 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6126 rsurface.tvector3f_bufferobject = 0;
6127 rsurface.tvector3f_bufferoffset = 0;
6128 rsurface.normal3f = rsurface.array_deformednormal3f;
6129 rsurface.normal3f_bufferobject = 0;
6130 rsurface.normal3f_bufferoffset = 0;
6132 case Q3DEFORM_NORMAL:
6133 // deform the normals to make reflections wavey
6134 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6136 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6137 for (j = 0;j < surface->num_vertices;j++)
6140 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
6141 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6142 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
6143 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6144 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6145 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6146 VectorNormalize(normal);
6148 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);
6150 rsurface.svector3f = rsurface.array_deformedsvector3f;
6151 rsurface.svector3f_bufferobject = 0;
6152 rsurface.svector3f_bufferoffset = 0;
6153 rsurface.tvector3f = rsurface.array_deformedtvector3f;
6154 rsurface.tvector3f_bufferobject = 0;
6155 rsurface.tvector3f_bufferoffset = 0;
6156 rsurface.normal3f = rsurface.array_deformednormal3f;
6157 rsurface.normal3f_bufferobject = 0;
6158 rsurface.normal3f_bufferoffset = 0;
6161 // deform vertex array to make wavey water and flags and such
6162 waveparms[0] = deform->waveparms[0];
6163 waveparms[1] = deform->waveparms[1];
6164 waveparms[2] = deform->waveparms[2];
6165 waveparms[3] = deform->waveparms[3];
6166 // this is how a divisor of vertex influence on deformation
6167 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6168 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6169 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6171 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6172 for (j = 0;j < surface->num_vertices;j++)
6174 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
6175 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
6176 // if the wavefunc depends on time, evaluate it per-vertex
6179 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6180 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6182 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
6185 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6186 rsurface.vertex3f_bufferobject = 0;
6187 rsurface.vertex3f_bufferoffset = 0;
6189 case Q3DEFORM_BULGE:
6190 // deform vertex array to make the surface have moving bulges
6191 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6193 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6194 for (j = 0;j < surface->num_vertices;j++)
6196 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6197 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6200 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6201 rsurface.vertex3f_bufferobject = 0;
6202 rsurface.vertex3f_bufferoffset = 0;
6205 // deform vertex array
6206 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6207 VectorScale(deform->parms, scale, waveparms);
6208 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6210 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6211 for (j = 0;j < surface->num_vertices;j++)
6212 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6214 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6215 rsurface.vertex3f_bufferobject = 0;
6216 rsurface.vertex3f_bufferoffset = 0;
6220 // generate texcoords based on the chosen texcoord source
6221 switch(rsurface.texture->tcgen.tcgen)
6224 case Q3TCGEN_TEXTURE:
6225 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6226 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6227 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6229 case Q3TCGEN_LIGHTMAP:
6230 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6231 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6232 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6234 case Q3TCGEN_VECTOR:
6235 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6237 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6238 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)
6240 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6241 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6244 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6245 rsurface.texcoordtexture2f_bufferobject = 0;
6246 rsurface.texcoordtexture2f_bufferoffset = 0;
6248 case Q3TCGEN_ENVIRONMENT:
6249 // make environment reflections using a spheremap
6250 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6252 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6253 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6254 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6255 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6256 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6258 // identical to Q3A's method, but executed in worldspace so
6259 // carried models can be shiny too
6261 float viewer[3], d, reflected[3], worldreflected[3];
6263 VectorSubtract(rsurface.modelorg, vertex, viewer);
6264 // VectorNormalize(viewer);
6266 d = DotProduct(normal, viewer);
6268 reflected[0] = normal[0]*2*d - viewer[0];
6269 reflected[1] = normal[1]*2*d - viewer[1];
6270 reflected[2] = normal[2]*2*d - viewer[2];
6271 // note: this is proportinal to viewer, so we can normalize later
6273 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6274 VectorNormalize(worldreflected);
6276 // note: this sphere map only uses world x and z!
6277 // so positive and negative y will LOOK THE SAME.
6278 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6279 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6282 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6283 rsurface.texcoordtexture2f_bufferobject = 0;
6284 rsurface.texcoordtexture2f_bufferoffset = 0;
6287 // the only tcmod that needs software vertex processing is turbulent, so
6288 // check for it here and apply the changes if needed
6289 // and we only support that as the first one
6290 // (handling a mixture of turbulent and other tcmods would be problematic
6291 // without punting it entirely to a software path)
6292 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6294 amplitude = rsurface.texture->tcmods[0].parms[1];
6295 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6296 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6298 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6299 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)
6301 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6302 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6305 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6306 rsurface.texcoordtexture2f_bufferobject = 0;
6307 rsurface.texcoordtexture2f_bufferoffset = 0;
6309 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6310 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6311 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6312 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6315 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
6318 const msurface_t *surface = texturesurfacelist[0];
6319 const msurface_t *surface2;
6324 // TODO: lock all array ranges before render, rather than on each surface
6325 if (texturenumsurfaces == 1)
6327 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6328 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);
6330 else if (r_batchmode.integer == 2)
6332 #define MAXBATCHTRIANGLES 4096
6333 int batchtriangles = 0;
6334 int batchelements[MAXBATCHTRIANGLES*3];
6335 for (i = 0;i < texturenumsurfaces;i = j)
6337 surface = texturesurfacelist[i];
6339 if (surface->num_triangles > MAXBATCHTRIANGLES)
6341 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);
6344 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6345 batchtriangles = surface->num_triangles;
6346 firstvertex = surface->num_firstvertex;
6347 endvertex = surface->num_firstvertex + surface->num_vertices;
6348 for (;j < texturenumsurfaces;j++)
6350 surface2 = texturesurfacelist[j];
6351 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6353 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6354 batchtriangles += surface2->num_triangles;
6355 firstvertex = min(firstvertex, surface2->num_firstvertex);
6356 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6358 surface2 = texturesurfacelist[j-1];
6359 numvertices = endvertex - firstvertex;
6360 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6363 else if (r_batchmode.integer == 1)
6365 for (i = 0;i < texturenumsurfaces;i = j)
6367 surface = texturesurfacelist[i];
6368 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6369 if (texturesurfacelist[j] != surface2)
6371 surface2 = texturesurfacelist[j-1];
6372 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6373 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6374 GL_LockArrays(surface->num_firstvertex, numvertices);
6375 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6380 for (i = 0;i < texturenumsurfaces;i++)
6382 surface = texturesurfacelist[i];
6383 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6384 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);
6389 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6391 int i, planeindex, vertexindex;
6395 r_waterstate_waterplane_t *p, *bestp;
6396 msurface_t *surface;
6397 if (r_waterstate.renderingscene)
6399 for (i = 0;i < texturenumsurfaces;i++)
6401 surface = texturesurfacelist[i];
6402 if (lightmaptexunit >= 0)
6403 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6404 if (deluxemaptexunit >= 0)
6405 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6406 // pick the closest matching water plane
6409 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6412 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6414 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6415 d += fabs(PlaneDiff(vert, &p->plane));
6417 if (bestd > d || !bestp)
6425 if (refractiontexunit >= 0)
6426 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6427 if (reflectiontexunit >= 0)
6428 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6432 if (refractiontexunit >= 0)
6433 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6434 if (reflectiontexunit >= 0)
6435 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6437 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6438 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);
6442 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6446 const msurface_t *surface = texturesurfacelist[0];
6447 const msurface_t *surface2;
6452 // TODO: lock all array ranges before render, rather than on each surface
6453 if (texturenumsurfaces == 1)
6455 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6456 if (deluxemaptexunit >= 0)
6457 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6458 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6459 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);
6461 else if (r_batchmode.integer == 2)
6463 #define MAXBATCHTRIANGLES 4096
6464 int batchtriangles = 0;
6465 int batchelements[MAXBATCHTRIANGLES*3];
6466 for (i = 0;i < texturenumsurfaces;i = j)
6468 surface = texturesurfacelist[i];
6469 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6470 if (deluxemaptexunit >= 0)
6471 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6473 if (surface->num_triangles > MAXBATCHTRIANGLES)
6475 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);
6478 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6479 batchtriangles = surface->num_triangles;
6480 firstvertex = surface->num_firstvertex;
6481 endvertex = surface->num_firstvertex + surface->num_vertices;
6482 for (;j < texturenumsurfaces;j++)
6484 surface2 = texturesurfacelist[j];
6485 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6487 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6488 batchtriangles += surface2->num_triangles;
6489 firstvertex = min(firstvertex, surface2->num_firstvertex);
6490 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6492 surface2 = texturesurfacelist[j-1];
6493 numvertices = endvertex - firstvertex;
6494 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6497 else if (r_batchmode.integer == 1)
6500 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6501 for (i = 0;i < texturenumsurfaces;i = j)
6503 surface = texturesurfacelist[i];
6504 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6505 if (texturesurfacelist[j] != surface2)
6507 Con_Printf(" %i", j - i);
6510 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6512 for (i = 0;i < texturenumsurfaces;i = j)
6514 surface = texturesurfacelist[i];
6515 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6516 if (deluxemaptexunit >= 0)
6517 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6518 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6519 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6522 Con_Printf(" %i", j - i);
6524 surface2 = texturesurfacelist[j-1];
6525 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6526 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6527 GL_LockArrays(surface->num_firstvertex, numvertices);
6528 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6536 for (i = 0;i < texturenumsurfaces;i++)
6538 surface = texturesurfacelist[i];
6539 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6540 if (deluxemaptexunit >= 0)
6541 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6542 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6543 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);
6548 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6551 int texturesurfaceindex;
6552 if (r_showsurfaces.integer == 2)
6554 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6556 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6557 for (j = 0;j < surface->num_triangles;j++)
6559 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6560 GL_Color(f, f, f, 1);
6561 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6567 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6569 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6570 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6571 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);
6572 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6573 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);
6578 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6580 int texturesurfaceindex;
6583 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6585 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6586 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)
6594 rsurface.lightmapcolor4f = rsurface.array_color4f;
6595 rsurface.lightmapcolor4f_bufferobject = 0;
6596 rsurface.lightmapcolor4f_bufferoffset = 0;
6599 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6601 int texturesurfaceindex;
6605 if (rsurface.lightmapcolor4f)
6607 // generate color arrays for the surfaces in this list
6608 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6610 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6611 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)
6613 f = FogPoint_Model(v);
6623 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6625 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6626 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)
6628 f = FogPoint_Model(v);
6636 rsurface.lightmapcolor4f = rsurface.array_color4f;
6637 rsurface.lightmapcolor4f_bufferobject = 0;
6638 rsurface.lightmapcolor4f_bufferoffset = 0;
6641 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6643 int texturesurfaceindex;
6647 if (!rsurface.lightmapcolor4f)
6649 // generate color arrays for the surfaces in this list
6650 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6652 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6653 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)
6655 f = FogPoint_Model(v);
6656 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6657 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6658 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6662 rsurface.lightmapcolor4f = rsurface.array_color4f;
6663 rsurface.lightmapcolor4f_bufferobject = 0;
6664 rsurface.lightmapcolor4f_bufferoffset = 0;
6667 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6669 int texturesurfaceindex;
6672 if (!rsurface.lightmapcolor4f)
6674 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6676 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6677 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)
6685 rsurface.lightmapcolor4f = rsurface.array_color4f;
6686 rsurface.lightmapcolor4f_bufferobject = 0;
6687 rsurface.lightmapcolor4f_bufferoffset = 0;
6690 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6692 int texturesurfaceindex;
6695 if (!rsurface.lightmapcolor4f)
6697 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6699 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6700 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)
6702 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6703 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6704 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6708 rsurface.lightmapcolor4f = rsurface.array_color4f;
6709 rsurface.lightmapcolor4f_bufferobject = 0;
6710 rsurface.lightmapcolor4f_bufferoffset = 0;
6713 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6716 rsurface.lightmapcolor4f = NULL;
6717 rsurface.lightmapcolor4f_bufferobject = 0;
6718 rsurface.lightmapcolor4f_bufferoffset = 0;
6719 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6720 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6721 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6722 GL_Color(r, g, b, a);
6723 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6726 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6728 // TODO: optimize applyfog && applycolor case
6729 // just apply fog if necessary, and tint the fog color array if necessary
6730 rsurface.lightmapcolor4f = NULL;
6731 rsurface.lightmapcolor4f_bufferobject = 0;
6732 rsurface.lightmapcolor4f_bufferoffset = 0;
6733 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6734 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6735 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6736 GL_Color(r, g, b, a);
6737 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6740 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6742 int texturesurfaceindex;
6746 if (texturesurfacelist[0]->lightmapinfo)
6748 // generate color arrays for the surfaces in this list
6749 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6751 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6752 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6754 if (surface->lightmapinfo->samples)
6756 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6757 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6758 VectorScale(lm, scale, c);
6759 if (surface->lightmapinfo->styles[1] != 255)
6761 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6763 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6764 VectorMA(c, scale, lm, c);
6765 if (surface->lightmapinfo->styles[2] != 255)
6768 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6769 VectorMA(c, scale, lm, c);
6770 if (surface->lightmapinfo->styles[3] != 255)
6773 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6774 VectorMA(c, scale, lm, c);
6784 rsurface.lightmapcolor4f = rsurface.array_color4f;
6785 rsurface.lightmapcolor4f_bufferobject = 0;
6786 rsurface.lightmapcolor4f_bufferoffset = 0;
6790 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6791 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6792 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6794 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6795 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6796 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6797 GL_Color(r, g, b, a);
6798 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6801 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6803 int texturesurfaceindex;
6806 float *v, *c, *c2, alpha;
6807 vec3_t ambientcolor;
6808 vec3_t diffusecolor;
6812 VectorCopy(rsurface.modellight_lightdir, lightdir);
6813 f = 0.5f * r_refdef.lightmapintensity;
6814 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6815 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6816 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6817 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6818 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6819 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6821 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6823 // generate color arrays for the surfaces in this list
6824 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6826 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6827 int numverts = surface->num_vertices;
6828 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6829 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6830 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6831 // q3-style directional shading
6832 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6834 if ((f = DotProduct(c2, lightdir)) > 0)
6835 VectorMA(ambientcolor, f, diffusecolor, c);
6837 VectorCopy(ambientcolor, c);
6845 rsurface.lightmapcolor4f = rsurface.array_color4f;
6846 rsurface.lightmapcolor4f_bufferobject = 0;
6847 rsurface.lightmapcolor4f_bufferoffset = 0;
6848 *applycolor = false;
6852 *r = ambientcolor[0];
6853 *g = ambientcolor[1];
6854 *b = ambientcolor[2];
6855 rsurface.lightmapcolor4f = NULL;
6856 rsurface.lightmapcolor4f_bufferobject = 0;
6857 rsurface.lightmapcolor4f_bufferoffset = 0;
6861 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6863 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6864 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6865 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6866 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6867 GL_Color(r, g, b, a);
6868 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6871 void RSurf_SetupDepthAndCulling(void)
6873 // submodels are biased to avoid z-fighting with world surfaces that they
6874 // may be exactly overlapping (avoids z-fighting artifacts on certain
6875 // doors and things in Quake maps)
6876 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6877 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6878 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6879 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6882 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6884 // transparent sky would be ridiculous
6885 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6887 R_SetupGenericShader(false);
6890 skyrendernow = false;
6891 // we have to force off the water clipping plane while rendering sky
6895 // restore entity matrix
6896 R_Mesh_Matrix(&rsurface.matrix);
6898 RSurf_SetupDepthAndCulling();
6900 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6901 // skymasking on them, and Quake3 never did sky masking (unlike
6902 // software Quake and software Quake2), so disable the sky masking
6903 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6904 // and skymasking also looks very bad when noclipping outside the
6905 // level, so don't use it then either.
6906 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6908 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6909 R_Mesh_ColorPointer(NULL, 0, 0);
6910 R_Mesh_ResetTextureState();
6911 if (skyrendermasked)
6913 R_SetupDepthOrShadowShader();
6914 // depth-only (masking)
6915 GL_ColorMask(0,0,0,0);
6916 // just to make sure that braindead drivers don't draw
6917 // anything despite that colormask...
6918 GL_BlendFunc(GL_ZERO, GL_ONE);
6922 R_SetupGenericShader(false);
6924 GL_BlendFunc(GL_ONE, GL_ZERO);
6926 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6927 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6928 if (skyrendermasked)
6929 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6931 R_Mesh_ResetTextureState();
6932 GL_Color(1, 1, 1, 1);
6935 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6937 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6940 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6941 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6942 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6943 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6944 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6945 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6946 if (rsurface.texture->backgroundcurrentskinframe)
6948 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6949 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6950 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6951 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6953 if(rsurface.texture->colormapping)
6955 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6956 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6958 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6959 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6960 R_Mesh_ColorPointer(NULL, 0, 0);
6962 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6964 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6966 // render background
6967 GL_BlendFunc(GL_ONE, GL_ZERO);
6969 GL_AlphaTest(false);
6971 GL_Color(1, 1, 1, 1);
6972 R_Mesh_ColorPointer(NULL, 0, 0);
6974 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6975 if (r_glsl_permutation)
6977 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6978 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6979 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6980 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6981 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6982 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6983 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);
6985 GL_LockArrays(0, 0);
6987 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6988 GL_DepthMask(false);
6989 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6990 R_Mesh_ColorPointer(NULL, 0, 0);
6992 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6993 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6994 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6997 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6998 if (!r_glsl_permutation)
7001 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7002 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7003 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7004 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7005 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7006 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7008 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7010 GL_BlendFunc(GL_ONE, GL_ZERO);
7012 GL_AlphaTest(false);
7016 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7017 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7018 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7021 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7023 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7024 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);
7026 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7030 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7031 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);
7033 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7035 GL_LockArrays(0, 0);
7038 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7040 // OpenGL 1.3 path - anything not completely ancient
7041 int texturesurfaceindex;
7042 qboolean applycolor;
7046 const texturelayer_t *layer;
7047 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7049 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7052 int layertexrgbscale;
7053 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7055 if (layerindex == 0)
7059 GL_AlphaTest(false);
7060 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7063 GL_DepthMask(layer->depthmask && writedepth);
7064 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7065 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7067 layertexrgbscale = 4;
7068 VectorScale(layer->color, 0.25f, layercolor);
7070 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7072 layertexrgbscale = 2;
7073 VectorScale(layer->color, 0.5f, layercolor);
7077 layertexrgbscale = 1;
7078 VectorScale(layer->color, 1.0f, layercolor);
7080 layercolor[3] = layer->color[3];
7081 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7082 R_Mesh_ColorPointer(NULL, 0, 0);
7083 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7084 switch (layer->type)
7086 case TEXTURELAYERTYPE_LITTEXTURE:
7087 memset(&m, 0, sizeof(m));
7088 m.tex[0] = R_GetTexture(r_texture_white);
7089 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7090 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7091 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7092 m.tex[1] = R_GetTexture(layer->texture);
7093 m.texmatrix[1] = layer->texmatrix;
7094 m.texrgbscale[1] = layertexrgbscale;
7095 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7096 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7097 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7098 R_Mesh_TextureState(&m);
7099 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7100 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7101 else if (rsurface.uselightmaptexture)
7102 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7104 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7106 case TEXTURELAYERTYPE_TEXTURE:
7107 memset(&m, 0, sizeof(m));
7108 m.tex[0] = R_GetTexture(layer->texture);
7109 m.texmatrix[0] = layer->texmatrix;
7110 m.texrgbscale[0] = layertexrgbscale;
7111 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7112 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7113 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7114 R_Mesh_TextureState(&m);
7115 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7117 case TEXTURELAYERTYPE_FOG:
7118 memset(&m, 0, sizeof(m));
7119 m.texrgbscale[0] = layertexrgbscale;
7122 m.tex[0] = R_GetTexture(layer->texture);
7123 m.texmatrix[0] = layer->texmatrix;
7124 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7125 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7126 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7128 R_Mesh_TextureState(&m);
7129 // generate a color array for the fog pass
7130 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7131 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7135 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7136 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)
7138 f = 1 - FogPoint_Model(v);
7139 c[0] = layercolor[0];
7140 c[1] = layercolor[1];
7141 c[2] = layercolor[2];
7142 c[3] = f * layercolor[3];
7145 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7148 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7150 GL_LockArrays(0, 0);
7153 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7155 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7156 GL_AlphaTest(false);
7160 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7162 // OpenGL 1.1 - crusty old voodoo path
7163 int texturesurfaceindex;
7167 const texturelayer_t *layer;
7168 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7170 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7172 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7174 if (layerindex == 0)
7178 GL_AlphaTest(false);
7179 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7182 GL_DepthMask(layer->depthmask && writedepth);
7183 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7184 R_Mesh_ColorPointer(NULL, 0, 0);
7185 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7186 switch (layer->type)
7188 case TEXTURELAYERTYPE_LITTEXTURE:
7189 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7191 // two-pass lit texture with 2x rgbscale
7192 // first the lightmap pass
7193 memset(&m, 0, sizeof(m));
7194 m.tex[0] = R_GetTexture(r_texture_white);
7195 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7196 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7197 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7198 R_Mesh_TextureState(&m);
7199 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7200 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7201 else if (rsurface.uselightmaptexture)
7202 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7204 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7205 GL_LockArrays(0, 0);
7206 // then apply the texture to it
7207 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7208 memset(&m, 0, sizeof(m));
7209 m.tex[0] = R_GetTexture(layer->texture);
7210 m.texmatrix[0] = layer->texmatrix;
7211 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7212 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7213 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7214 R_Mesh_TextureState(&m);
7215 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);
7219 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7220 memset(&m, 0, sizeof(m));
7221 m.tex[0] = R_GetTexture(layer->texture);
7222 m.texmatrix[0] = layer->texmatrix;
7223 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7224 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7225 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7226 R_Mesh_TextureState(&m);
7227 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7228 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);
7230 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);
7233 case TEXTURELAYERTYPE_TEXTURE:
7234 // singletexture unlit texture with transparency support
7235 memset(&m, 0, sizeof(m));
7236 m.tex[0] = R_GetTexture(layer->texture);
7237 m.texmatrix[0] = layer->texmatrix;
7238 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7239 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7240 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7241 R_Mesh_TextureState(&m);
7242 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);
7244 case TEXTURELAYERTYPE_FOG:
7245 // singletexture fogging
7246 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7249 memset(&m, 0, sizeof(m));
7250 m.tex[0] = R_GetTexture(layer->texture);
7251 m.texmatrix[0] = layer->texmatrix;
7252 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7253 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7254 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7255 R_Mesh_TextureState(&m);
7258 R_Mesh_ResetTextureState();
7259 // generate a color array for the fog pass
7260 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7264 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7265 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)
7267 f = 1 - FogPoint_Model(v);
7268 c[0] = layer->color[0];
7269 c[1] = layer->color[1];
7270 c[2] = layer->color[2];
7271 c[3] = f * layer->color[3];
7274 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7277 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7279 GL_LockArrays(0, 0);
7282 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7284 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7285 GL_AlphaTest(false);
7289 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7293 GL_AlphaTest(false);
7294 R_Mesh_ColorPointer(NULL, 0, 0);
7295 R_Mesh_ResetTextureState();
7296 R_SetupGenericShader(false);
7298 if(rsurface.texture && rsurface.texture->currentskinframe)
7300 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7301 c[3] *= rsurface.texture->currentalpha;
7311 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7313 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7314 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7315 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7318 // brighten it up (as texture value 127 means "unlit")
7319 c[0] *= 2 * r_refdef.view.colorscale;
7320 c[1] *= 2 * r_refdef.view.colorscale;
7321 c[2] *= 2 * r_refdef.view.colorscale;
7323 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7324 c[3] *= r_wateralpha.value;
7326 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7328 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7329 GL_DepthMask(false);
7331 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7333 GL_BlendFunc(GL_ONE, GL_ONE);
7334 GL_DepthMask(false);
7336 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7338 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7339 GL_DepthMask(false);
7341 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7343 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7344 GL_DepthMask(false);
7348 GL_BlendFunc(GL_ONE, GL_ZERO);
7349 GL_DepthMask(writedepth);
7352 rsurface.lightmapcolor4f = NULL;
7354 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7356 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7358 rsurface.lightmapcolor4f = NULL;
7359 rsurface.lightmapcolor4f_bufferobject = 0;
7360 rsurface.lightmapcolor4f_bufferoffset = 0;
7362 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7364 qboolean applycolor = true;
7367 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7369 r_refdef.lightmapintensity = 1;
7370 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7371 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7375 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7377 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7378 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7379 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7382 if(!rsurface.lightmapcolor4f)
7383 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7385 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7386 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7387 if(r_refdef.fogenabled)
7388 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7390 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7391 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7394 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7397 RSurf_SetupDepthAndCulling();
7398 if (r_showsurfaces.integer == 3)
7399 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7400 else if (r_glsl.integer && gl_support_fragment_shader)
7401 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7402 else if (gl_combine.integer && r_textureunits.integer >= 2)
7403 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7405 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7409 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7412 RSurf_SetupDepthAndCulling();
7413 if (r_showsurfaces.integer == 3)
7414 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7415 else if (r_glsl.integer && gl_support_fragment_shader)
7416 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7417 else if (gl_combine.integer && r_textureunits.integer >= 2)
7418 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7420 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7424 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7427 int texturenumsurfaces, endsurface;
7429 msurface_t *surface;
7430 msurface_t *texturesurfacelist[1024];
7432 // if the model is static it doesn't matter what value we give for
7433 // wantnormals and wanttangents, so this logic uses only rules applicable
7434 // to a model, knowing that they are meaningless otherwise
7435 if (ent == r_refdef.scene.worldentity)
7436 RSurf_ActiveWorldEntity();
7437 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7438 RSurf_ActiveModelEntity(ent, false, false);
7440 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7442 for (i = 0;i < numsurfaces;i = j)
7445 surface = rsurface.modelsurfaces + surfacelist[i];
7446 texture = surface->texture;
7447 rsurface.texture = R_GetCurrentTexture(texture);
7448 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7449 // scan ahead until we find a different texture
7450 endsurface = min(i + 1024, numsurfaces);
7451 texturenumsurfaces = 0;
7452 texturesurfacelist[texturenumsurfaces++] = surface;
7453 for (;j < endsurface;j++)
7455 surface = rsurface.modelsurfaces + surfacelist[j];
7456 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7458 texturesurfacelist[texturenumsurfaces++] = surface;
7460 // render the range of surfaces
7461 if (ent == r_refdef.scene.worldentity)
7462 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7464 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7466 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7467 GL_AlphaTest(false);
7470 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7472 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7476 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7478 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7480 RSurf_SetupDepthAndCulling();
7481 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7482 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7484 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7486 RSurf_SetupDepthAndCulling();
7487 GL_AlphaTest(false);
7488 R_Mesh_ColorPointer(NULL, 0, 0);
7489 R_Mesh_ResetTextureState();
7490 R_SetupGenericShader(false);
7491 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7493 GL_BlendFunc(GL_ONE, GL_ZERO);
7494 GL_Color(0, 0, 0, 1);
7495 GL_DepthTest(writedepth);
7496 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7498 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7500 RSurf_SetupDepthAndCulling();
7501 GL_AlphaTest(false);
7502 R_Mesh_ColorPointer(NULL, 0, 0);
7503 R_Mesh_ResetTextureState();
7504 R_SetupGenericShader(false);
7505 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7507 GL_BlendFunc(GL_ONE, GL_ZERO);
7509 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7511 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7512 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7513 else if (!rsurface.texture->currentnumlayers)
7515 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7517 // transparent surfaces get pushed off into the transparent queue
7518 int surfacelistindex;
7519 const msurface_t *surface;
7520 vec3_t tempcenter, center;
7521 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7523 surface = texturesurfacelist[surfacelistindex];
7524 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7525 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7526 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7527 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7528 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7533 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7534 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7539 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7543 // break the surface list down into batches by texture and use of lightmapping
7544 for (i = 0;i < numsurfaces;i = j)
7547 // texture is the base texture pointer, rsurface.texture is the
7548 // current frame/skin the texture is directing us to use (for example
7549 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7550 // use skin 1 instead)
7551 texture = surfacelist[i]->texture;
7552 rsurface.texture = R_GetCurrentTexture(texture);
7553 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7554 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7556 // if this texture is not the kind we want, skip ahead to the next one
7557 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7561 // simply scan ahead until we find a different texture or lightmap state
7562 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7564 // render the range of surfaces
7565 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7569 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7574 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7576 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7578 RSurf_SetupDepthAndCulling();
7579 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7580 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7582 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7584 RSurf_SetupDepthAndCulling();
7585 GL_AlphaTest(false);
7586 R_Mesh_ColorPointer(NULL, 0, 0);
7587 R_Mesh_ResetTextureState();
7588 R_SetupGenericShader(false);
7589 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7591 GL_BlendFunc(GL_ONE, GL_ZERO);
7592 GL_Color(0, 0, 0, 1);
7593 GL_DepthTest(writedepth);
7594 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7596 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7598 RSurf_SetupDepthAndCulling();
7599 GL_AlphaTest(false);
7600 R_Mesh_ColorPointer(NULL, 0, 0);
7601 R_Mesh_ResetTextureState();
7602 R_SetupGenericShader(false);
7603 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7605 GL_BlendFunc(GL_ONE, GL_ZERO);
7607 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7609 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7610 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7611 else if (!rsurface.texture->currentnumlayers)
7613 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7615 // transparent surfaces get pushed off into the transparent queue
7616 int surfacelistindex;
7617 const msurface_t *surface;
7618 vec3_t tempcenter, center;
7619 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7621 surface = texturesurfacelist[surfacelistindex];
7622 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7623 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7624 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7625 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7626 if (queueentity->transparent_offset) // transparent offset
7628 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
7629 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
7630 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
7632 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7637 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7638 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7643 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7647 // break the surface list down into batches by texture and use of lightmapping
7648 for (i = 0;i < numsurfaces;i = j)
7651 // texture is the base texture pointer, rsurface.texture is the
7652 // current frame/skin the texture is directing us to use (for example
7653 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7654 // use skin 1 instead)
7655 texture = surfacelist[i]->texture;
7656 rsurface.texture = R_GetCurrentTexture(texture);
7657 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7658 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7660 // if this texture is not the kind we want, skip ahead to the next one
7661 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7665 // simply scan ahead until we find a different texture or lightmap state
7666 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7668 // render the range of surfaces
7669 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7673 float locboxvertex3f[6*4*3] =
7675 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7676 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7677 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7678 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7679 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7680 1,0,0, 0,0,0, 0,1,0, 1,1,0
7683 unsigned short locboxelements[6*2*3] =
7693 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7696 cl_locnode_t *loc = (cl_locnode_t *)ent;
7698 float vertex3f[6*4*3];
7700 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7701 GL_DepthMask(false);
7702 GL_DepthRange(0, 1);
7703 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7705 GL_CullFace(GL_NONE);
7706 R_Mesh_Matrix(&identitymatrix);
7708 R_Mesh_VertexPointer(vertex3f, 0, 0);
7709 R_Mesh_ColorPointer(NULL, 0, 0);
7710 R_Mesh_ResetTextureState();
7711 R_SetupGenericShader(false);
7714 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7715 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7716 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7717 surfacelist[0] < 0 ? 0.5f : 0.125f);
7719 if (VectorCompare(loc->mins, loc->maxs))
7721 VectorSet(size, 2, 2, 2);
7722 VectorMA(loc->mins, -0.5f, size, mins);
7726 VectorCopy(loc->mins, mins);
7727 VectorSubtract(loc->maxs, loc->mins, size);
7730 for (i = 0;i < 6*4*3;)
7731 for (j = 0;j < 3;j++, i++)
7732 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7734 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7737 void R_DrawLocs(void)
7740 cl_locnode_t *loc, *nearestloc;
7742 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7743 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7745 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7746 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7750 void R_DrawDebugModel(entity_render_t *ent)
7752 int i, j, k, l, flagsmask;
7753 const int *elements;
7755 msurface_t *surface;
7756 dp_model_t *model = ent->model;
7759 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7761 R_Mesh_ColorPointer(NULL, 0, 0);
7762 R_Mesh_ResetTextureState();
7763 R_SetupGenericShader(false);
7764 GL_DepthRange(0, 1);
7765 GL_DepthTest(!r_showdisabledepthtest.integer);
7766 GL_DepthMask(false);
7767 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7769 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7771 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7772 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7774 if (brush->colbrushf && brush->colbrushf->numtriangles)
7776 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7777 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);
7778 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7781 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7783 if (surface->num_collisiontriangles)
7785 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7786 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);
7787 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7792 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7794 if (r_showtris.integer || r_shownormals.integer)
7796 if (r_showdisabledepthtest.integer)
7798 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7799 GL_DepthMask(false);
7803 GL_BlendFunc(GL_ONE, GL_ZERO);
7806 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7808 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7810 rsurface.texture = R_GetCurrentTexture(surface->texture);
7811 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7813 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7814 if (r_showtris.value > 0)
7816 if (!rsurface.texture->currentlayers->depthmask)
7817 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7818 else if (ent == r_refdef.scene.worldentity)
7819 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7821 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7822 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7823 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7824 R_Mesh_ColorPointer(NULL, 0, 0);
7825 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7826 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7827 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7828 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);
7829 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7832 if (r_shownormals.value < 0)
7835 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7837 VectorCopy(rsurface.vertex3f + l * 3, v);
7838 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7839 qglVertex3f(v[0], v[1], v[2]);
7840 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7841 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7842 qglVertex3f(v[0], v[1], v[2]);
7847 if (r_shownormals.value > 0)
7850 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7852 VectorCopy(rsurface.vertex3f + l * 3, v);
7853 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7854 qglVertex3f(v[0], v[1], v[2]);
7855 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7856 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7857 qglVertex3f(v[0], v[1], v[2]);
7862 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7864 VectorCopy(rsurface.vertex3f + l * 3, v);
7865 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7866 qglVertex3f(v[0], v[1], v[2]);
7867 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7868 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7869 qglVertex3f(v[0], v[1], v[2]);
7874 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7876 VectorCopy(rsurface.vertex3f + l * 3, v);
7877 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7878 qglVertex3f(v[0], v[1], v[2]);
7879 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7880 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7881 qglVertex3f(v[0], v[1], v[2]);
7888 rsurface.texture = NULL;
7892 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7893 int r_maxsurfacelist = 0;
7894 msurface_t **r_surfacelist = NULL;
7895 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7897 int i, j, endj, f, flagsmask;
7899 dp_model_t *model = r_refdef.scene.worldmodel;
7900 msurface_t *surfaces;
7901 unsigned char *update;
7902 int numsurfacelist = 0;
7906 if (r_maxsurfacelist < model->num_surfaces)
7908 r_maxsurfacelist = model->num_surfaces;
7910 Mem_Free(r_surfacelist);
7911 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7914 RSurf_ActiveWorldEntity();
7916 surfaces = model->data_surfaces;
7917 update = model->brushq1.lightmapupdateflags;
7919 // update light styles on this submodel
7920 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7922 model_brush_lightstyleinfo_t *style;
7923 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7925 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7927 int *list = style->surfacelist;
7928 style->value = r_refdef.scene.lightstylevalue[style->style];
7929 for (j = 0;j < style->numsurfaces;j++)
7930 update[list[j]] = true;
7935 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7939 R_DrawDebugModel(r_refdef.scene.worldentity);
7940 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7946 rsurface.uselightmaptexture = false;
7947 rsurface.texture = NULL;
7948 rsurface.rtlight = NULL;
7950 // add visible surfaces to draw list
7951 for (i = 0;i < model->nummodelsurfaces;i++)
7953 j = model->sortedmodelsurfaces[i];
7954 if (r_refdef.viewcache.world_surfacevisible[j])
7955 r_surfacelist[numsurfacelist++] = surfaces + j;
7957 // update lightmaps if needed
7959 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7960 if (r_refdef.viewcache.world_surfacevisible[j])
7962 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7963 // don't do anything if there were no surfaces
7964 if (!numsurfacelist)
7966 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7969 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7970 GL_AlphaTest(false);
7972 // add to stats if desired
7973 if (r_speeds.integer && !skysurfaces && !depthonly)
7975 r_refdef.stats.world_surfaces += numsurfacelist;
7976 for (j = 0;j < numsurfacelist;j++)
7977 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7979 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7982 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7984 int i, j, endj, f, flagsmask;
7986 dp_model_t *model = ent->model;
7987 msurface_t *surfaces;
7988 unsigned char *update;
7989 int numsurfacelist = 0;
7993 if (r_maxsurfacelist < model->num_surfaces)
7995 r_maxsurfacelist = model->num_surfaces;
7997 Mem_Free(r_surfacelist);
7998 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8001 // if the model is static it doesn't matter what value we give for
8002 // wantnormals and wanttangents, so this logic uses only rules applicable
8003 // to a model, knowing that they are meaningless otherwise
8004 if (ent == r_refdef.scene.worldentity)
8005 RSurf_ActiveWorldEntity();
8006 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8007 RSurf_ActiveModelEntity(ent, false, false);
8009 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8011 surfaces = model->data_surfaces;
8012 update = model->brushq1.lightmapupdateflags;
8014 // update light styles
8015 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8017 model_brush_lightstyleinfo_t *style;
8018 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8020 if (style->value != r_refdef.scene.lightstylevalue[style->style])
8022 int *list = style->surfacelist;
8023 style->value = r_refdef.scene.lightstylevalue[style->style];
8024 for (j = 0;j < style->numsurfaces;j++)
8025 update[list[j]] = true;
8030 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8034 R_DrawDebugModel(ent);
8035 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8041 rsurface.uselightmaptexture = false;
8042 rsurface.texture = NULL;
8043 rsurface.rtlight = NULL;
8045 // add visible surfaces to draw list
8046 for (i = 0;i < model->nummodelsurfaces;i++)
8047 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8048 // don't do anything if there were no surfaces
8049 if (!numsurfacelist)
8051 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8054 // update lightmaps if needed
8056 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8058 R_BuildLightMap(ent, surfaces + j);
8059 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8060 GL_AlphaTest(false);
8062 // add to stats if desired
8063 if (r_speeds.integer && !skysurfaces && !depthonly)
8065 r_refdef.stats.entities_surfaces += numsurfacelist;
8066 for (j = 0;j < numsurfacelist;j++)
8067 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8069 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity