2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
31 static int r_frame = 0; ///< used only by R_GetCurrentTexture
38 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
39 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
40 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
41 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
42 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
43 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
44 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
45 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
47 cvar_t r_animcache = {CVAR_SAVE, "r_animcache", "1", "cache animation frames to save CPU usage, primarily optimizes shadows and reflections"};
49 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
50 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
51 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
52 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
53 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
54 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
55 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
56 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
57 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
58 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
59 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
60 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
61 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
62 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
63 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
64 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
65 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
66 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
67 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
68 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
69 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
70 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
71 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
72 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
73 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
74 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
75 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
76 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
77 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
78 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
79 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
80 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
81 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
82 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
83 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
84 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
86 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
87 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
88 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
89 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
90 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
91 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
92 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
93 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
95 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
97 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
98 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
99 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
100 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
101 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
102 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
103 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
104 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
105 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
106 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
107 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
109 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
110 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
111 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
112 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
113 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
115 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
116 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
117 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
118 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
120 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
121 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
122 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
123 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
124 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
125 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
126 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
128 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
129 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
130 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
131 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
133 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
135 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
137 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
139 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
140 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
141 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
142 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
143 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
144 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
145 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
147 extern cvar_t v_glslgamma;
149 extern qboolean v_flipped_state;
151 static struct r_bloomstate_s
156 int bloomwidth, bloomheight;
158 int screentexturewidth, screentextureheight;
159 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
161 int bloomtexturewidth, bloomtextureheight;
162 rtexture_t *texture_bloom;
164 // arrays for rendering the screen passes
165 float screentexcoord2f[8];
166 float bloomtexcoord2f[8];
167 float offsettexcoord2f[8];
169 r_viewport_t viewport;
173 r_waterstate_t r_waterstate;
175 /// shadow volume bsp struct with automatically growing nodes buffer
178 rtexture_t *r_texture_blanknormalmap;
179 rtexture_t *r_texture_white;
180 rtexture_t *r_texture_grey128;
181 rtexture_t *r_texture_black;
182 rtexture_t *r_texture_notexture;
183 rtexture_t *r_texture_whitecube;
184 rtexture_t *r_texture_normalizationcube;
185 rtexture_t *r_texture_fogattenuation;
186 rtexture_t *r_texture_gammaramps;
187 unsigned int r_texture_gammaramps_serial;
188 //rtexture_t *r_texture_fogintensity;
190 unsigned int r_queries[R_MAX_OCCLUSION_QUERIES];
191 unsigned int r_numqueries;
192 unsigned int r_maxqueries;
194 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
195 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
197 /// vertex coordinates for a quad that covers the screen exactly
198 const float r_screenvertex3f[12] =
206 extern void R_DrawModelShadows(void);
208 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
211 for (i = 0;i < verts;i++)
222 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
225 for (i = 0;i < verts;i++)
235 // FIXME: move this to client?
238 if (gamemode == GAME_NEHAHRA)
240 Cvar_Set("gl_fogenable", "0");
241 Cvar_Set("gl_fogdensity", "0.2");
242 Cvar_Set("gl_fogred", "0.3");
243 Cvar_Set("gl_foggreen", "0.3");
244 Cvar_Set("gl_fogblue", "0.3");
246 r_refdef.fog_density = 0;
247 r_refdef.fog_red = 0;
248 r_refdef.fog_green = 0;
249 r_refdef.fog_blue = 0;
250 r_refdef.fog_alpha = 1;
251 r_refdef.fog_start = 0;
252 r_refdef.fog_end = 0;
255 float FogForDistance(vec_t dist)
257 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
258 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
261 float FogPoint_World(const vec3_t p)
263 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
266 float FogPoint_Model(const vec3_t p)
268 return FogForDistance(VectorDistance((p), rsurface.modelorg) * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
271 static void R_BuildBlankTextures(void)
273 unsigned char data[4];
274 data[2] = 128; // normal X
275 data[1] = 128; // normal Y
276 data[0] = 255; // normal Z
277 data[3] = 128; // height
278 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
283 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
288 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
293 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
296 static void R_BuildNoTexture(void)
299 unsigned char pix[16][16][4];
300 // this makes a light grey/dark grey checkerboard texture
301 for (y = 0;y < 16;y++)
303 for (x = 0;x < 16;x++)
305 if ((y < 8) ^ (x < 8))
321 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
324 static void R_BuildWhiteCube(void)
326 unsigned char data[6*1*1*4];
327 memset(data, 255, sizeof(data));
328 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
331 static void R_BuildNormalizationCube(void)
335 vec_t s, t, intensity;
337 unsigned char data[6][NORMSIZE][NORMSIZE][4];
338 for (side = 0;side < 6;side++)
340 for (y = 0;y < NORMSIZE;y++)
342 for (x = 0;x < NORMSIZE;x++)
344 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
345 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
380 intensity = 127.0f / sqrt(DotProduct(v, v));
381 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
382 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
383 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
384 data[side][y][x][3] = 255;
388 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
391 static void R_BuildFogTexture(void)
395 unsigned char data1[FOGWIDTH][4];
396 //unsigned char data2[FOGWIDTH][4];
399 r_refdef.fogmasktable_start = r_refdef.fog_start;
400 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
401 r_refdef.fogmasktable_range = r_refdef.fogrange;
402 r_refdef.fogmasktable_density = r_refdef.fog_density;
404 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
405 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
407 d = (x * r - r_refdef.fogmasktable_start);
408 if(developer.integer >= 100)
409 Con_Printf("%f ", d);
411 if (r_fog_exp2.integer)
412 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
414 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
415 if(developer.integer >= 100)
416 Con_Printf(" : %f ", alpha);
417 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
418 if(developer.integer >= 100)
419 Con_Printf(" = %f\n", alpha);
420 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
423 for (x = 0;x < FOGWIDTH;x++)
425 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
430 //data2[x][0] = 255 - b;
431 //data2[x][1] = 255 - b;
432 //data2[x][2] = 255 - b;
435 if (r_texture_fogattenuation)
437 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
438 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
442 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
443 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
447 static const char *builtinshaderstring =
448 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
449 "// written by Forest 'LordHavoc' Hale\n"
450 "#ifdef USESHADOWMAPRECT\n"
451 "#extension GL_ARB_texture_rectangle : enable\n"
452 "# ifdef HASTEXTUREGATHER\n"
453 "# extension GL_ARB_texture_gather : enable\n"
455 "# ifdef HASTEXTURE4\n"
456 "# extension GL_AMD_texture_texture4 : enable\n"
457 "# define textureGather texture4\n"
462 "// common definitions between vertex shader and fragment shader:\n"
464 "//#ifdef __GLSL_CG_DATA_TYPES\n"
465 "//# define myhalf half\n"
466 "//# define myhalf2 half2\n"
467 "//# define myhalf3half3\n"
468 "//# define myhalf4 half4\n"
470 "# define myhalf float\n"
471 "# define myhalf2 vec2\n"
472 "# define myhalf3 vec3\n"
473 "# define myhalf4 vec4\n"
476 "#ifdef MODE_DEPTH_OR_SHADOW\n"
478 "# ifdef VERTEX_SHADER\n"
481 " gl_Position = ftransform();\n"
486 "#ifdef MODE_SHOWDEPTH\n"
487 "# ifdef VERTEX_SHADER\n"
490 " gl_Position = ftransform();\n"
491 " gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
494 "# ifdef FRAGMENT_SHADER\n"
497 " gl_FragColor = gl_Color;\n"
501 "#else // !MODE_SHOWDEPTH\n"
503 "#ifdef MODE_POSTPROCESS\n"
504 "# ifdef VERTEX_SHADER\n"
507 " gl_FrontColor = gl_Color;\n"
508 " gl_Position = ftransform();\n"
509 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
511 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
515 "# ifdef FRAGMENT_SHADER\n"
517 "uniform sampler2D Texture_First;\n"
519 "uniform sampler2D Texture_Second;\n"
521 "#ifdef USEGAMMARAMPS\n"
522 "uniform sampler2D Texture_GammaRamps;\n"
524 "#ifdef USESATURATION\n"
525 "uniform float Saturation;\n"
527 "#ifdef USEVIEWTINT\n"
528 "uniform vec4 TintColor;\n"
530 "//uncomment these if you want to use them:\n"
531 "uniform vec4 UserVec1;\n"
532 "// uniform vec4 UserVec2;\n"
533 "// uniform vec4 UserVec3;\n"
534 "// uniform vec4 UserVec4;\n"
535 "// uniform float ClientTime;\n"
536 "uniform vec2 PixelSize;\n"
539 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
541 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
543 "#ifdef USEVIEWTINT\n"
544 " gl_FragColor = mix(gl_FragColor, TintColor, TintColor.a);\n"
547 "#ifdef USEPOSTPROCESSING\n"
548 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
549 "// 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"
550 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
551 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
552 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
553 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2( 0.707107, 0.707107)) * UserVec1.y;\n"
554 " gl_FragColor += texture2D(Texture_First, gl_TexCoord[0].xy + PixelSize*UserVec1.x*vec2(-0.453990, 0.891007)) * UserVec1.y;\n"
555 " gl_FragColor /= (1 + 5 * UserVec1.y);\n"
558 "#ifdef USESATURATION\n"
559 " //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
560 " myhalf y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
561 " //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
562 " gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
565 "#ifdef USEGAMMARAMPS\n"
566 " gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
567 " gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
568 " gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
575 "#ifdef MODE_GENERIC\n"
576 "# ifdef VERTEX_SHADER\n"
579 " gl_FrontColor = gl_Color;\n"
580 "# ifdef USEDIFFUSE\n"
581 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
583 "# ifdef USESPECULAR\n"
584 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
586 " gl_Position = ftransform();\n"
589 "# ifdef FRAGMENT_SHADER\n"
591 "# ifdef USEDIFFUSE\n"
592 "uniform sampler2D Texture_First;\n"
594 "# ifdef USESPECULAR\n"
595 "uniform sampler2D Texture_Second;\n"
600 " gl_FragColor = gl_Color;\n"
601 "# ifdef USEDIFFUSE\n"
602 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
605 "# ifdef USESPECULAR\n"
606 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
608 "# ifdef USECOLORMAPPING\n"
609 " gl_FragColor *= tex2;\n"
612 " gl_FragColor += tex2;\n"
614 "# ifdef USEVERTEXTEXTUREBLEND\n"
615 " gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
620 "#else // !MODE_GENERIC\n"
622 "varying vec2 TexCoord;\n"
623 "#ifdef USEVERTEXTEXTUREBLEND\n"
624 "varying vec2 TexCoord2;\n"
626 "varying vec2 TexCoordLightmap;\n"
628 "#ifdef MODE_LIGHTSOURCE\n"
629 "varying vec3 CubeVector;\n"
632 "#ifdef MODE_LIGHTSOURCE\n"
633 "varying vec3 LightVector;\n"
635 "#ifdef MODE_LIGHTDIRECTION\n"
636 "varying vec3 LightVector;\n"
639 "varying vec3 EyeVector;\n"
641 "varying vec3 EyeVectorModelSpace;\n"
644 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
645 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
646 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
648 "#ifdef MODE_WATER\n"
649 "varying vec4 ModelViewProjectionPosition;\n"
651 "#ifdef MODE_REFRACTION\n"
652 "varying vec4 ModelViewProjectionPosition;\n"
654 "#ifdef USEREFLECTION\n"
655 "varying vec4 ModelViewProjectionPosition;\n"
662 "// vertex shader specific:\n"
663 "#ifdef VERTEX_SHADER\n"
665 "uniform vec3 LightPosition;\n"
666 "uniform vec3 EyePosition;\n"
667 "uniform vec3 LightDir;\n"
669 "// 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"
673 " gl_FrontColor = gl_Color;\n"
674 " // copy the surface texcoord\n"
675 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
676 "#ifdef USEVERTEXTEXTUREBLEND\n"
677 " TexCoord2 = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord0);\n"
679 "#ifndef MODE_LIGHTSOURCE\n"
680 "# ifndef MODE_LIGHTDIRECTION\n"
681 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
685 "#ifdef MODE_LIGHTSOURCE\n"
686 " // transform vertex position into light attenuation/cubemap space\n"
687 " // (-1 to +1 across the light box)\n"
688 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
690 " // transform unnormalized light direction into tangent space\n"
691 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
692 " // normalize it per pixel)\n"
693 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
694 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
695 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
696 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
699 "#ifdef MODE_LIGHTDIRECTION\n"
700 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
701 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
702 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
705 " // transform unnormalized eye direction into tangent space\n"
707 " vec3 EyeVectorModelSpace;\n"
709 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
710 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
711 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
712 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
714 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
715 " VectorS = gl_MultiTexCoord1.xyz;\n"
716 " VectorT = gl_MultiTexCoord2.xyz;\n"
717 " VectorR = gl_MultiTexCoord3.xyz;\n"
720 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
721 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
722 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
723 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
726 "// transform vertex to camera space, using ftransform to match non-VS\n"
728 " gl_Position = ftransform();\n"
730 "#ifdef MODE_WATER\n"
731 " ModelViewProjectionPosition = gl_Position;\n"
733 "#ifdef MODE_REFRACTION\n"
734 " ModelViewProjectionPosition = gl_Position;\n"
736 "#ifdef USEREFLECTION\n"
737 " ModelViewProjectionPosition = gl_Position;\n"
741 "#endif // VERTEX_SHADER\n"
746 "// fragment shader specific:\n"
747 "#ifdef FRAGMENT_SHADER\n"
749 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
750 "uniform sampler2D Texture_Normal;\n"
751 "uniform sampler2D Texture_Color;\n"
752 "uniform sampler2D Texture_Gloss;\n"
753 "uniform sampler2D Texture_Glow;\n"
754 "uniform sampler2D Texture_SecondaryNormal;\n"
755 "uniform sampler2D Texture_SecondaryColor;\n"
756 "uniform sampler2D Texture_SecondaryGloss;\n"
757 "uniform sampler2D Texture_SecondaryGlow;\n"
758 "uniform sampler2D Texture_Pants;\n"
759 "uniform sampler2D Texture_Shirt;\n"
760 "uniform sampler2D Texture_FogMask;\n"
761 "uniform sampler2D Texture_Lightmap;\n"
762 "uniform sampler2D Texture_Deluxemap;\n"
763 "uniform sampler2D Texture_Refraction;\n"
764 "uniform sampler2D Texture_Reflection;\n"
765 "uniform sampler2D Texture_Attenuation;\n"
766 "uniform samplerCube Texture_Cube;\n"
768 "#define showshadowmap 0\n"
770 "#ifdef USESHADOWMAPRECT\n"
771 "# ifdef USESHADOWSAMPLER\n"
772 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
774 "uniform sampler2DRect Texture_ShadowMapRect;\n"
777 "uniform samplerCube Texture_CubeProjection;\n"
780 "uniform myhalf3 LightColor;\n"
781 "uniform myhalf3 AmbientColor;\n"
782 "uniform myhalf3 DiffuseColor;\n"
783 "uniform myhalf3 SpecularColor;\n"
784 "uniform myhalf3 Color_Pants;\n"
785 "uniform myhalf3 Color_Shirt;\n"
786 "uniform myhalf3 FogColor;\n"
788 "uniform myhalf4 TintColor;\n"
791 "//#ifdef MODE_WATER\n"
792 "uniform vec4 DistortScaleRefractReflect;\n"
793 "uniform vec4 ScreenScaleRefractReflect;\n"
794 "uniform vec4 ScreenCenterRefractReflect;\n"
795 "uniform myhalf4 RefractColor;\n"
796 "uniform myhalf4 ReflectColor;\n"
797 "uniform myhalf ReflectFactor;\n"
798 "uniform myhalf ReflectOffset;\n"
800 "//# ifdef MODE_REFRACTION\n"
801 "//uniform vec4 DistortScaleRefractReflect;\n"
802 "//uniform vec4 ScreenScaleRefractReflect;\n"
803 "//uniform vec4 ScreenCenterRefractReflect;\n"
804 "//uniform myhalf4 RefractColor;\n"
805 "//# ifdef USEREFLECTION\n"
806 "//uniform myhalf4 ReflectColor;\n"
809 "//# ifdef USEREFLECTION\n"
810 "//uniform vec4 DistortScaleRefractReflect;\n"
811 "//uniform vec4 ScreenScaleRefractReflect;\n"
812 "//uniform vec4 ScreenCenterRefractReflect;\n"
813 "//uniform myhalf4 ReflectColor;\n"
818 "uniform myhalf GlowScale;\n"
819 "uniform myhalf SceneBrightness;\n"
821 "uniform float OffsetMapping_Scale;\n"
822 "uniform float OffsetMapping_Bias;\n"
823 "uniform float FogRangeRecip;\n"
825 "uniform myhalf AmbientScale;\n"
826 "uniform myhalf DiffuseScale;\n"
827 "uniform myhalf SpecularScale;\n"
828 "uniform myhalf SpecularPower;\n"
830 "#ifdef USEOFFSETMAPPING\n"
831 "vec2 OffsetMapping(vec2 TexCoord)\n"
833 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
834 " // 14 sample relief mapping: linear search and then binary search\n"
835 " // this basically steps forward a small amount repeatedly until it finds\n"
836 " // itself inside solid, then jitters forward and back using decreasing\n"
837 " // amounts to find the impact\n"
838 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
839 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
840 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
841 " vec3 RT = vec3(TexCoord, 1);\n"
842 " OffsetVector *= 0.1;\n"
843 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
844 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
845 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
846 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
847 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
848 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
849 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
850 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
851 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
852 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
853 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
854 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
855 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
856 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
859 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
860 " // this basically moves forward the full distance, and then backs up based\n"
861 " // on height of samples\n"
862 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
863 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
864 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
865 " TexCoord += OffsetVector;\n"
866 " OffsetVector *= 0.333;\n"
867 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
868 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
869 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
870 " return TexCoord;\n"
873 "#endif // USEOFFSETMAPPING\n"
875 "#ifdef USESHADOWMAPRECT \n"
876 "uniform vec4 ShadowMap_TextureScale;\n"
878 "uniform vec4 ShadowMap_Parameters;\n"
881 "vec3 GetShadowMapTC2D(vec3 dir)\n"
883 " vec3 adir = abs(dir);\n"
888 " if (adir.x > adir.y)\n"
890 " if (adir.x > adir.z)\n"
893 " if (dir.x >= 0.0)\n"
896 " tc = vec2(-dir.z, -dir.y);\n"
897 " offset = vec2(0.5, 0.5);\n"
902 " tc = vec2( dir.z, -dir.y);\n"
903 " offset = vec2(1.5, 0.5);\n"
909 " if (dir.z >= 0.0)\n"
912 " tc = vec2( dir.x, -dir.y);\n"
913 " offset = vec2(0.5, 2.5);\n"
918 " tc = vec2(-dir.x, -dir.y);\n"
919 " offset = vec2(1.5, 2.5);\n"
925 " if (adir.y > adir.z)\n"
928 " if (dir.y >= 0.0)\n"
931 " tc = vec2( dir.x, dir.z);\n"
932 " offset = vec2(0.5, 1.5);\n"
937 " tc = vec2( dir.x, -dir.z);\n"
938 " offset = vec2(1.5, 1.5);\n"
944 " if (dir.z >= 0.0)\n"
947 " tc = vec2(dir.x, -dir.y);\n"
948 " offset = vec2(0.5, 2.5);\n"
953 " tc = vec2(-dir.x, -dir.y);\n"
954 " offset = vec2(1.5, 2.5);\n"
959 " return vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma + vec3(offset * ShadowMap_Parameters.y, ShadowMap_Parameters.z);\n"
961 " return vec3(textureCube(Texture_CubeProjection, dir.xyz).ra * ShadowMap_TextureScale.xy, ShadowMap_TextureScale.z + ShadowMap_TextureScale.w / max(max(adir.x, adir.y), adir.z));\n"
965 "#endif // USESHADOWMAPRECT\n"
967 "#if !showshadowmap\n"
968 "# ifdef USESHADOWMAPRECT\n"
969 "float ShadowMapCompare(vec3 dir)\n"
971 " vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
973 "# ifdef USESHADOWSAMPLER\n"
975 "# ifdef USESHADOWMAPPCF\n"
976 " f = dot(vec4(0.25),\n"
977 " vec4(shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3(-0.4, 1.0, 0.0)).r,\n"
978 " shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3(-1.0, -0.4, 0.0)).r,\n"
979 " shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3( 0.4, -1.0, 0.0)).r,\n"
980 " shadow2DRect(Texture_ShadowMapRect, shadowmaptc.xyz + vec3( 1.0, 0.4, 0.0)).r));\n"
982 " f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
987 "# ifdef USESHADOWMAPPCF\n"
988 "# if defined(HASTEXTUREGATHER) || defined(HASTEXTURE4)\n"
989 " vec2 offset = fract(shadowmaptc.xy - 0.5);\n"
990 " vec4 group1 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, -1.0))),\n"
991 " group2 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, -1.0))),\n"
992 " group3 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, 1.0))),\n"
993 " group4 = step(shadowmaptc.z, textureGather(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, 1.0))),\n"
994 " cols = vec4(group1.ab, group2.ab) + vec4(group3.rg, group4.rg) +\n"
995 " mix(vec4(group1.rg, group2.rg), vec4(group3.ab, group4.ab), offset.y);\n"
996 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
998 " vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
999 " vec4 row1 = step(shadowmaptc.z,\n"
1000 " vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0, -1.0)).r,\n"
1001 " texture2DRect(Texture_ShadowMapRect, center + vec2( 0.0, -1.0)).r,\n"
1002 " texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0, -1.0)).r,\n"
1003 " texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0, -1.0)).r)),\n"
1004 " row2 = step(shadowmaptc.z,\n"
1005 " vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0, 0.0)).r,\n"
1006 " texture2DRect(Texture_ShadowMapRect, center).r,\n"
1007 " texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0, 0.0)).r,\n"
1008 " texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0, 0.0)).r)),\n"
1009 " row3 = step(shadowmaptc.z,\n"
1010 " vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0, 1.0)).r,\n"
1011 " texture2DRect(Texture_ShadowMapRect, center + vec2( 0.0, 1.0)).r,\n"
1012 " texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0, 1.0)).r,\n"
1013 " texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0, 1.0)).r)),\n"
1014 " row4 = step(shadowmaptc.z,\n"
1015 " vec4(texture2DRect(Texture_ShadowMapRect, center + vec2(-1.0, 2.0)).r,\n"
1016 " texture2DRect(Texture_ShadowMapRect, center + vec2( 0.0, 2.0)).r,\n"
1017 " texture2DRect(Texture_ShadowMapRect, center + vec2( 1.0, 2.0)).r,\n"
1018 " texture2DRect(Texture_ShadowMapRect, center + vec2( 2.0, 2.0)).r)),\n"
1019 " cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1020 " f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1022 " vec2 offset = fract(shadowmaptc.xy);\n"
1023 " vec3 row1 = step(shadowmaptc.z,\n"
1024 " vec3(texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, -1.0)).r,\n"
1025 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 0.0, -1.0)).r,\n"
1026 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, -1.0)).r)),\n"
1027 " row2 = step(shadowmaptc.z,\n"
1028 " vec3(texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, 0.0)).r,\n"
1029 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r,\n"
1030 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, 0.0)).r)),\n"
1031 " row3 = step(shadowmaptc.z,\n"
1032 " vec3(texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(-1.0, 1.0)).r,\n"
1033 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 0.0, 1.0)).r,\n"
1034 " texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2( 1.0, 1.0)).r)),\n"
1035 " cols = row2 + mix(row1, row3, offset.y);\n"
1036 " f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1039 " f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1050 "#ifdef MODE_WATER\n"
1055 "#ifdef USEOFFSETMAPPING\n"
1056 " // apply offsetmapping\n"
1057 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1058 "#define TexCoord TexCoordOffset\n"
1061 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1062 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1063 " vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1064 " vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1065 " // FIXME temporary hack to detect the case that the reflection\n"
1066 " // gets blackened at edges due to leaving the area that contains actual\n"
1068 " // Remove this 'ack once we have a better way to stop this thing from\n"
1070 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1071 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1072 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1073 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1074 " ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1075 " f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1076 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1077 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1078 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1079 " ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1080 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1081 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1084 "#else // !MODE_WATER\n"
1085 "#ifdef MODE_REFRACTION\n"
1087 "// refraction pass\n"
1090 "#ifdef USEOFFSETMAPPING\n"
1091 " // apply offsetmapping\n"
1092 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1093 "#define TexCoord TexCoordOffset\n"
1096 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1097 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1098 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1099 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1100 " // FIXME temporary hack to detect the case that the reflection\n"
1101 " // gets blackened at edges due to leaving the area that contains actual\n"
1103 " // Remove this 'ack once we have a better way to stop this thing from\n"
1105 " float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1106 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1107 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1108 " f *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1109 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1110 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
1113 "#else // !MODE_REFRACTION\n"
1116 "#ifdef USEOFFSETMAPPING\n"
1117 " // apply offsetmapping\n"
1118 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1119 "#define TexCoord TexCoordOffset\n"
1122 " // combine the diffuse textures (base, pants, shirt)\n"
1123 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1124 "#ifdef USECOLORMAPPING\n"
1125 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1127 "#ifdef USEVERTEXTEXTUREBLEND\n"
1128 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1129 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1130 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1131 " color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1133 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1136 "#ifdef USEDIFFUSE\n"
1137 " // get the surface normal and the gloss color\n"
1138 "# ifdef USEVERTEXTEXTUREBLEND\n"
1139 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1140 "# ifdef USESPECULAR\n"
1141 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1144 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1145 "# ifdef USESPECULAR\n"
1146 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1153 "#ifdef MODE_LIGHTSOURCE\n"
1154 " // light source\n"
1156 " // calculate surface normal, light normal, and specular normal\n"
1157 " // compute color intensity for the two textures (colormap and glossmap)\n"
1158 " // scale by light color and attenuation as efficiently as possible\n"
1159 " // (do as much scalar math as possible rather than vector math)\n"
1160 "# ifdef USEDIFFUSE\n"
1161 " // get the light normal\n"
1162 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1164 "# ifdef USESPECULAR\n"
1165 "# ifndef USEEXACTSPECULARMATH\n"
1166 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1169 " // calculate directional shading\n"
1170 "# ifdef USEEXACTSPECULARMATH\n"
1171 " 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"
1173 " 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"
1176 "# ifdef USEDIFFUSE\n"
1177 " // calculate directional shading\n"
1178 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
1180 " // calculate directionless shading\n"
1181 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1185 "#ifdef USESHADOWMAPRECT\n"
1186 "#if !showshadowmap\n"
1187 " color.rgb *= ShadowMapCompare(CubeVector);\n"
1191 "# ifdef USECUBEFILTER\n"
1192 " // apply light cubemap filter\n"
1193 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
1194 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1196 "#endif // MODE_LIGHTSOURCE\n"
1201 "#ifdef MODE_LIGHTDIRECTION\n"
1202 " // directional model lighting\n"
1203 "# ifdef USEDIFFUSE\n"
1204 " // get the light normal\n"
1205 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
1207 "# ifdef USESPECULAR\n"
1208 " // calculate directional shading\n"
1209 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1210 "# ifdef USEEXACTSPECULARMATH\n"
1211 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1213 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
1214 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1217 "# ifdef USEDIFFUSE\n"
1219 " // calculate directional shading\n"
1220 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
1222 " color.rgb *= AmbientColor;\n"
1225 "#endif // MODE_LIGHTDIRECTION\n"
1230 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1231 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
1233 " // get the light normal\n"
1234 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1235 " myhalf3 diffusenormal;\n"
1236 " diffusenormal.x = dot(diffusenormal_modelspace, myhalf3(VectorS));\n"
1237 " diffusenormal.y = dot(diffusenormal_modelspace, myhalf3(VectorT));\n"
1238 " diffusenormal.z = dot(diffusenormal_modelspace, myhalf3(VectorR));\n"
1239 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1240 " // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1241 " // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1242 " // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1243 " // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1244 " // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1245 " // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1246 " // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1247 " // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1248 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / max(0.25, diffusenormal.z)), 0.0)));\n"
1249 " // 0.25 supports up to 75.5 degrees normal/deluxe angle\n"
1250 "# ifdef USESPECULAR\n"
1251 "# ifdef USEEXACTSPECULARMATH\n"
1252 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(normalize(diffusenormal), surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1254 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1255 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1259 " // apply lightmap color\n"
1260 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1261 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1266 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1267 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1269 " // get the light normal\n"
1270 " myhalf3 diffusenormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1271 " // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1272 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal) / diffusenormal.z), 0.0)));\n"
1273 "# ifdef USESPECULAR\n"
1274 "# ifdef USEEXACTSPECULARMATH\n"
1275 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(reflect(diffusenormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1277 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
1278 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1282 " // apply lightmap color\n"
1283 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1284 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1289 "#ifdef MODE_LIGHTMAP\n"
1290 " // apply lightmap color\n"
1291 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
1292 "#endif // MODE_LIGHTMAP\n"
1297 "#ifdef MODE_VERTEXCOLOR\n"
1298 " // apply lightmap color\n"
1299 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
1300 "#endif // MODE_VERTEXCOLOR\n"
1305 "#ifdef MODE_FLATCOLOR\n"
1306 "#endif // MODE_FLATCOLOR\n"
1314 " color *= TintColor;\n"
1317 "#ifdef USEVERTEXTEXTUREBLEND\n"
1318 " color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend);\n"
1320 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1324 " color.rgb *= SceneBrightness;\n"
1326 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1328 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1331 " // 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"
1332 "#ifdef USEREFLECTION\n"
1333 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1334 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1335 " vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1336 " vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1337 " // FIXME temporary hack to detect the case that the reflection\n"
1338 " // gets blackened at edges due to leaving the area that contains actual\n"
1340 " // Remove this 'ack once we have a better way to stop this thing from\n"
1342 " float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1343 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1344 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1345 " f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1346 " ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1347 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1350 " gl_FragColor = vec4(color);\n"
1352 "#if showshadowmap\n"
1353 "# ifdef USESHADOWMAPRECT\n"
1354 "# ifdef USESHADOWSAMPLER\n"
1355 " gl_FragColor = shadow2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xyz);\n"
1357 " gl_FragColor = texture2DRect(Texture_ShadowMapRect, GetShadowMapTC2D(CubeVector).xy);\n"
1362 "#endif // !MODE_REFRACTION\n"
1363 "#endif // !MODE_WATER\n"
1365 "#endif // FRAGMENT_SHADER\n"
1367 "#endif // !MODE_GENERIC\n"
1368 "#endif // !MODE_POSTPROCESS\n"
1369 "#endif // !MODE_SHOWDEPTH\n"
1370 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1373 typedef struct shaderpermutationinfo_s
1375 const char *pretext;
1378 shaderpermutationinfo_t;
1380 typedef struct shadermodeinfo_s
1382 const char *vertexfilename;
1383 const char *geometryfilename;
1384 const char *fragmentfilename;
1385 const char *pretext;
1390 typedef enum shaderpermutation_e
1392 SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
1393 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1394 SHADERPERMUTATION_VIEWTINT = 1<<1, ///< view tint (postprocessing only)
1395 SHADERPERMUTATION_COLORMAPPING = 1<<2, ///< indicates this is a colormapped skin
1396 SHADERPERMUTATION_SATURATION = 1<<2, ///< saturation (postprocessing only)
1397 SHADERPERMUTATION_FOG = 1<<3, ///< tint the color by fog color or black if using additive blend mode
1398 SHADERPERMUTATION_GAMMARAMPS = 1<<3, ///< gamma (postprocessing only)
1399 SHADERPERMUTATION_CUBEFILTER = 1<<4, ///< (lightsource) use cubemap light filter
1400 SHADERPERMUTATION_GLOW = 1<<5, ///< (lightmap) blend in an additive glow texture
1401 SHADERPERMUTATION_BLOOM = 1<<5, ///< bloom (postprocessing only)
1402 SHADERPERMUTATION_SPECULAR = 1<<6, ///< (lightsource or deluxemapping) render specular effects
1403 SHADERPERMUTATION_POSTPROCESSING = 1<<6, ///< user defined postprocessing (postprocessing only)
1404 SHADERPERMUTATION_EXACTSPECULARMATH = 1<<7, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
1405 SHADERPERMUTATION_REFLECTION = 1<<8, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1406 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, ///< adjust texcoords to roughly simulate a displacement mapped surface
1407 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1408 SHADERPERMUTATION_SHADOWMAPRECT = 1<<11, ///< (lightsource) use shadowmap rectangle texture as light filter
1409 SHADERPERMUTATION_SHADOWMAPPCF = 1<<12, //< (lightsource) use percentage closer filtering on shadowmap test results
1410 SHADERPERMUTATION_SHADOWSAMPLER = 1<<13, //< (lightsource) use hardware shadowmap test
1411 SHADERPERMUTATION_LIMIT = 1<<14, ///< size of permutations array
1412 SHADERPERMUTATION_COUNT = 14 ///< size of shaderpermutationinfo array
1414 shaderpermutation_t;
1416 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1417 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1419 {"#define USEDIFFUSE\n", " diffuse"},
1420 {"#define USEVERTEXTEXTUREBLEND\n#define USEVIEWTINT\n", " vertextextureblend/tint"},
1421 {"#define USECOLORMAPPING\n#define USESATURATION\n", " colormapping/saturation"},
1422 {"#define USEFOG\n#define USEGAMMARAMPS\n", " fog/gammaramps"},
1423 {"#define USECUBEFILTER\n", " cubefilter"},
1424 {"#define USEGLOW\n#define USEBLOOM\n", " glow/bloom"},
1425 {"#define USESPECULAR\n#define USEPOSTPROCESSING", " specular/postprocessing"},
1426 {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
1427 {"#define USEREFLECTION\n", " reflection"},
1428 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1429 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1430 {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
1431 {"#define USESHADOWMAPPCF\n", " shadowmappcf"},
1432 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
1435 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
1436 typedef enum shadermode_e
1438 SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
1439 SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
1440 SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
1441 SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1442 SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
1443 SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1444 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1445 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1446 SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1447 SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
1448 SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
1449 SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
1450 SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
1455 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1456 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1458 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1459 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1460 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1461 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1462 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1463 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1464 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1465 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1466 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1467 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1468 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1469 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1470 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
1473 typedef struct r_glsl_permutation_s
1475 /// indicates if we have tried compiling this permutation already
1477 /// 0 if compilation failed
1479 /// locations of detected uniforms in program object, or -1 if not found
1480 int loc_Texture_First;
1481 int loc_Texture_Second;
1482 int loc_Texture_GammaRamps;
1483 int loc_Texture_Normal;
1484 int loc_Texture_Color;
1485 int loc_Texture_Gloss;
1486 int loc_Texture_Glow;
1487 int loc_Texture_SecondaryNormal;
1488 int loc_Texture_SecondaryColor;
1489 int loc_Texture_SecondaryGloss;
1490 int loc_Texture_SecondaryGlow;
1491 int loc_Texture_Pants;
1492 int loc_Texture_Shirt;
1493 int loc_Texture_FogMask;
1494 int loc_Texture_Lightmap;
1495 int loc_Texture_Deluxemap;
1496 int loc_Texture_Attenuation;
1497 int loc_Texture_Cube;
1498 int loc_Texture_Refraction;
1499 int loc_Texture_Reflection;
1500 int loc_Texture_ShadowMapRect;
1501 int loc_Texture_CubeProjection;
1503 int loc_LightPosition;
1504 int loc_EyePosition;
1505 int loc_Color_Pants;
1506 int loc_Color_Shirt;
1507 int loc_FogRangeRecip;
1508 int loc_AmbientScale;
1509 int loc_DiffuseScale;
1510 int loc_SpecularScale;
1511 int loc_SpecularPower;
1513 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1514 int loc_OffsetMapping_Scale;
1516 int loc_AmbientColor;
1517 int loc_DiffuseColor;
1518 int loc_SpecularColor;
1520 int loc_ContrastBoostCoeff; ///< 1 - 1/ContrastBoost
1521 int loc_GammaCoeff; ///< 1 / gamma
1522 int loc_DistortScaleRefractReflect;
1523 int loc_ScreenScaleRefractReflect;
1524 int loc_ScreenCenterRefractReflect;
1525 int loc_RefractColor;
1526 int loc_ReflectColor;
1527 int loc_ReflectFactor;
1528 int loc_ReflectOffset;
1536 int loc_ShadowMap_TextureScale;
1537 int loc_ShadowMap_Parameters;
1539 r_glsl_permutation_t;
1541 /// information about each possible shader permutation
1542 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1543 /// currently selected permutation
1544 r_glsl_permutation_t *r_glsl_permutation;
1546 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1549 if (!filename || !filename[0])
1551 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1554 if (printfromdisknotice)
1555 Con_DPrint("from disk... ");
1556 return shaderstring;
1558 else if (!strcmp(filename, "glsl/default.glsl"))
1560 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1561 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1563 return shaderstring;
1566 static void R_GLSL_CompilePermutation(unsigned int mode, unsigned int permutation)
1569 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1570 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1571 int vertstrings_count = 0;
1572 int geomstrings_count = 0;
1573 int fragstrings_count = 0;
1574 char *vertexstring, *geometrystring, *fragmentstring;
1575 const char *vertstrings_list[32+3];
1576 const char *geomstrings_list[32+3];
1577 const char *fragstrings_list[32+3];
1578 char permutationname[256];
1585 permutationname[0] = 0;
1586 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1587 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1588 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1590 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1592 // the first pretext is which type of shader to compile as
1593 // (later these will all be bound together as a program object)
1594 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1595 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1596 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1598 // the second pretext is the mode (for example a light source)
1599 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1600 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1601 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1602 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1604 // now add all the permutation pretexts
1605 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1607 if (permutation & (1<<i))
1609 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1610 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1611 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1612 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1616 // keep line numbers correct
1617 vertstrings_list[vertstrings_count++] = "\n";
1618 geomstrings_list[geomstrings_count++] = "\n";
1619 fragstrings_list[fragstrings_count++] = "\n";
1623 // now append the shader text itself
1624 vertstrings_list[vertstrings_count++] = vertexstring;
1625 geomstrings_list[geomstrings_count++] = geometrystring;
1626 fragstrings_list[fragstrings_count++] = fragmentstring;
1628 // if any sources were NULL, clear the respective list
1630 vertstrings_count = 0;
1631 if (!geometrystring)
1632 geomstrings_count = 0;
1633 if (!fragmentstring)
1634 fragstrings_count = 0;
1636 // compile the shader program
1637 if (vertstrings_count + geomstrings_count + fragstrings_count)
1638 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1642 qglUseProgramObjectARB(p->program);CHECKGLERROR
1643 // look up all the uniform variable names we care about, so we don't
1644 // have to look them up every time we set them
1645 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1646 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1647 p->loc_Texture_GammaRamps = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
1648 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1649 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1650 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1651 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1652 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1653 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1654 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1655 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1656 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1657 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1658 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1659 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1660 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1661 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1662 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1663 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1664 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1665 p->loc_Texture_ShadowMapRect = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
1666 p->loc_Texture_CubeProjection = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
1667 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1668 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1669 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1670 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1671 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1672 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1673 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1674 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1675 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1676 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1677 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1678 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1679 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1680 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1681 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1682 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1683 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1684 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1685 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1686 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1687 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1688 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1689 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1690 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1691 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1692 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1693 p->loc_GammaCoeff = qglGetUniformLocationARB(p->program, "GammaCoeff");
1694 p->loc_UserVec1 = qglGetUniformLocationARB(p->program, "UserVec1");
1695 p->loc_UserVec2 = qglGetUniformLocationARB(p->program, "UserVec2");
1696 p->loc_UserVec3 = qglGetUniformLocationARB(p->program, "UserVec3");
1697 p->loc_UserVec4 = qglGetUniformLocationARB(p->program, "UserVec4");
1698 p->loc_ClientTime = qglGetUniformLocationARB(p->program, "ClientTime");
1699 p->loc_PixelSize = qglGetUniformLocationARB(p->program, "PixelSize");
1700 p->loc_Saturation = qglGetUniformLocationARB(p->program, "Saturation");
1701 p->loc_ShadowMap_TextureScale = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
1702 p->loc_ShadowMap_Parameters = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
1703 // initialize the samplers to refer to the texture units we use
1704 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1705 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1706 if (p->loc_Texture_GammaRamps >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps , GL20TU_GAMMARAMPS);
1707 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1708 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1709 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1710 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1711 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1712 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1713 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1714 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1715 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1716 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1717 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1718 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1719 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1720 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1721 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1722 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1723 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1724 if (p->loc_Texture_ShadowMapRect >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect , GL20TU_SHADOWMAPRECT);
1725 if (p->loc_Texture_CubeProjection >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
1727 if (developer.integer)
1728 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1731 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1735 Mem_Free(vertexstring);
1737 Mem_Free(geometrystring);
1739 Mem_Free(fragmentstring);
1742 void R_GLSL_Restart_f(void)
1745 unsigned int permutation;
1746 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1747 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1748 if (r_glsl_permutations[mode][permutation].program)
1749 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1750 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1753 void R_GLSL_DumpShader_f(void)
1757 qfile_t *file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1760 Con_Printf("failed to write to glsl/default.glsl\n");
1764 FS_Print(file, "/* The engine may define the following macros:\n");
1765 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1766 for (i = 0;i < SHADERMODE_COUNT;i++)
1767 FS_Print(file, shadermodeinfo[i].pretext);
1768 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1769 FS_Print(file, shaderpermutationinfo[i].pretext);
1770 FS_Print(file, "*/\n");
1771 FS_Print(file, builtinshaderstring);
1774 Con_Printf("glsl/default.glsl written\n");
1777 void R_SetupShader_SetPermutation(unsigned int mode, unsigned int permutation)
1779 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1780 if (r_glsl_permutation != perm)
1782 r_glsl_permutation = perm;
1783 if (!r_glsl_permutation->program)
1785 if (!r_glsl_permutation->compiled)
1786 R_GLSL_CompilePermutation(mode, permutation);
1787 if (!r_glsl_permutation->program)
1789 // remove features until we find a valid permutation
1791 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1793 // reduce i more quickly whenever it would not remove any bits
1794 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1795 if (!(permutation & j))
1798 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1799 if (!r_glsl_permutation->compiled)
1800 R_GLSL_CompilePermutation(mode, permutation);
1801 if (r_glsl_permutation->program)
1804 if (i >= SHADERPERMUTATION_COUNT)
1806 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");
1807 Cvar_SetValueQuick(&r_glsl, 0);
1808 R_GLSL_Restart_f(); // unload shaders
1809 return; // no bit left to clear
1814 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1818 void R_SetupGenericShader(qboolean usetexture)
1820 if (gl_support_fragment_shader)
1822 if (r_glsl.integer && r_glsl_usegeneric.integer)
1823 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1824 else if (r_glsl_permutation)
1826 r_glsl_permutation = NULL;
1827 qglUseProgramObjectARB(0);CHECKGLERROR
1832 void R_SetupGenericTwoTextureShader(int texturemode)
1834 if (gl_support_fragment_shader)
1836 if (r_glsl.integer && r_glsl_usegeneric.integer)
1837 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))));
1838 else if (r_glsl_permutation)
1840 r_glsl_permutation = NULL;
1841 qglUseProgramObjectARB(0);CHECKGLERROR
1844 if (!r_glsl_permutation)
1846 if (texturemode == GL_DECAL && gl_combine.integer)
1847 texturemode = GL_INTERPOLATE_ARB;
1848 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1852 void R_SetupDepthOrShadowShader(void)
1854 if (gl_support_fragment_shader)
1856 if (r_glsl.integer && r_glsl_usegeneric.integer)
1857 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1858 else if (r_glsl_permutation)
1860 r_glsl_permutation = NULL;
1861 qglUseProgramObjectARB(0);CHECKGLERROR
1866 void R_SetupShowDepthShader(void)
1868 if (gl_support_fragment_shader)
1870 if (r_glsl.integer && r_glsl_usegeneric.integer)
1871 R_SetupShader_SetPermutation(SHADERMODE_SHOWDEPTH, 0);
1872 else if (r_glsl_permutation)
1874 r_glsl_permutation = NULL;
1875 qglUseProgramObjectARB(0);CHECKGLERROR
1880 extern rtexture_t *r_shadow_attenuationgradienttexture;
1881 extern rtexture_t *r_shadow_attenuation2dtexture;
1882 extern rtexture_t *r_shadow_attenuation3dtexture;
1883 extern float r_shadow_shadowmap_bias;
1884 extern float r_shadow_shadowmap_texturescale[4];
1885 extern float r_shadow_shadowmap_parameters[4];
1886 extern int r_shadow_shadowmode;
1887 extern int r_shadow_shadowmapfilter;
1888 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1890 // select a permutation of the lighting shader appropriate to this
1891 // combination of texture, entity, light source, and fogging, only use the
1892 // minimum features necessary to avoid wasting rendering time in the
1893 // fragment shader on features that are not being used
1894 unsigned int permutation = 0;
1895 unsigned int mode = 0;
1896 // TODO: implement geometry-shader based shadow volumes someday
1897 if (r_glsl_offsetmapping.integer)
1899 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1900 if (r_glsl_offsetmapping_reliefmapping.integer)
1901 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1903 if (rsurfacepass == RSURFPASS_BACKGROUND)
1905 // distorted background
1906 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1907 mode = SHADERMODE_WATER;
1909 mode = SHADERMODE_REFRACTION;
1911 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1914 mode = SHADERMODE_LIGHTSOURCE;
1915 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1916 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1917 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1918 permutation |= SHADERPERMUTATION_CUBEFILTER;
1919 if (diffusescale > 0)
1920 permutation |= SHADERPERMUTATION_DIFFUSE;
1921 if (specularscale > 0)
1922 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1923 if (r_refdef.fogenabled)
1924 permutation |= SHADERPERMUTATION_FOG;
1925 if (rsurface.texture->colormapping)
1926 permutation |= SHADERPERMUTATION_COLORMAPPING;
1927 if (r_shadow_shadowmode)
1928 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
1929 if (r_shadow_shadowmapfilter == 3)
1930 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
1931 else if (r_shadow_shadowmapfilter == 2)
1932 permutation |= SHADERPERMUTATION_SHADOWMAPPCF | SHADERPERMUTATION_SHADOWSAMPLER;
1933 else if (r_shadow_shadowmapfilter == 1)
1934 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
1936 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1938 // unshaded geometry (fullbright or ambient model lighting)
1939 mode = SHADERMODE_FLATCOLOR;
1940 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1941 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1942 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1943 permutation |= SHADERPERMUTATION_GLOW;
1944 if (r_refdef.fogenabled)
1945 permutation |= SHADERPERMUTATION_FOG;
1946 if (rsurface.texture->colormapping)
1947 permutation |= SHADERPERMUTATION_COLORMAPPING;
1948 if (r_glsl_offsetmapping.integer)
1950 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1951 if (r_glsl_offsetmapping_reliefmapping.integer)
1952 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1954 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1955 permutation |= SHADERPERMUTATION_REFLECTION;
1957 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1959 // directional model lighting
1960 mode = SHADERMODE_LIGHTDIRECTION;
1961 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1962 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1963 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1964 permutation |= SHADERPERMUTATION_GLOW;
1965 permutation |= SHADERPERMUTATION_DIFFUSE;
1966 if (specularscale > 0)
1967 permutation |= SHADERPERMUTATION_SPECULAR;
1968 if (r_refdef.fogenabled)
1969 permutation |= SHADERPERMUTATION_FOG;
1970 if (rsurface.texture->colormapping)
1971 permutation |= SHADERPERMUTATION_COLORMAPPING;
1972 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1973 permutation |= SHADERPERMUTATION_REFLECTION;
1975 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1977 // ambient model lighting
1978 mode = SHADERMODE_LIGHTDIRECTION;
1979 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1980 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1981 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1982 permutation |= SHADERPERMUTATION_GLOW;
1983 if (r_refdef.fogenabled)
1984 permutation |= SHADERPERMUTATION_FOG;
1985 if (rsurface.texture->colormapping)
1986 permutation |= SHADERPERMUTATION_COLORMAPPING;
1987 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1988 permutation |= SHADERPERMUTATION_REFLECTION;
1993 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1995 // deluxemapping (light direction texture)
1996 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1997 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1999 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2000 permutation |= SHADERPERMUTATION_DIFFUSE;
2001 if (specularscale > 0)
2002 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2004 else if (r_glsl_deluxemapping.integer >= 2)
2006 // fake deluxemapping (uniform light direction in tangentspace)
2007 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2008 permutation |= SHADERPERMUTATION_DIFFUSE;
2009 if (specularscale > 0)
2010 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2012 else if (rsurface.uselightmaptexture)
2014 // ordinary lightmapping (q1bsp, q3bsp)
2015 mode = SHADERMODE_LIGHTMAP;
2019 // ordinary vertex coloring (q3bsp)
2020 mode = SHADERMODE_VERTEXCOLOR;
2022 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2023 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2024 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2025 permutation |= SHADERPERMUTATION_GLOW;
2026 if (r_refdef.fogenabled)
2027 permutation |= SHADERPERMUTATION_FOG;
2028 if (rsurface.texture->colormapping)
2029 permutation |= SHADERPERMUTATION_COLORMAPPING;
2030 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2031 permutation |= SHADERPERMUTATION_REFLECTION;
2033 if(permutation & SHADERPERMUTATION_SPECULAR)
2034 if(r_shadow_glossexact.integer)
2035 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
2036 R_SetupShader_SetPermutation(mode, permutation);
2037 if (mode == SHADERMODE_LIGHTSOURCE)
2039 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2040 if (permutation & SHADERPERMUTATION_DIFFUSE)
2042 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
2043 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
2044 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
2045 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
2049 // ambient only is simpler
2050 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]);
2051 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
2052 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
2053 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
2055 // additive passes are only darkened by fog, not tinted
2056 if (r_glsl_permutation->loc_FogColor >= 0)
2057 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2058 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1], r_shadow_shadowmap_texturescale[2], r_shadow_shadowmap_texturescale[3]);
2059 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]);
2063 if (mode == SHADERMODE_LIGHTDIRECTION)
2065 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);
2066 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);
2067 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);
2068 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]);
2072 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_refdef.scene.ambient * 1.0f / 128.0f);
2073 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
2074 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
2076 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]);
2077 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
2078 // additive passes are only darkened by fog, not tinted
2079 if (r_glsl_permutation->loc_FogColor >= 0)
2081 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2082 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2084 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2086 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);
2087 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]);
2088 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]);
2089 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
2090 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
2091 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2092 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2094 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
2095 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
2096 if (r_glsl_permutation->loc_Color_Pants >= 0)
2098 if (rsurface.texture->currentskinframe->pants)
2099 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2101 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2103 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2105 if (rsurface.texture->currentskinframe->shirt)
2106 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2108 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2110 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip * Matrix4x4_ScaleFromMatrix(&rsurface.matrix));
2111 if(permutation & SHADERPERMUTATION_EXACTSPECULARMATH)
2113 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * 0.25);
2117 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
2119 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2123 #define SKINFRAME_HASH 1024
2127 int loadsequence; // incremented each level change
2128 memexpandablearray_t array;
2129 skinframe_t *hash[SKINFRAME_HASH];
2132 r_skinframe_t r_skinframe;
2134 void R_SkinFrame_PrepareForPurge(void)
2136 r_skinframe.loadsequence++;
2137 // wrap it without hitting zero
2138 if (r_skinframe.loadsequence >= 200)
2139 r_skinframe.loadsequence = 1;
2142 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
2146 // mark the skinframe as used for the purging code
2147 skinframe->loadsequence = r_skinframe.loadsequence;
2150 void R_SkinFrame_Purge(void)
2154 for (i = 0;i < SKINFRAME_HASH;i++)
2156 for (s = r_skinframe.hash[i];s;s = s->next)
2158 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
2160 if (s->merged == s->base)
2162 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
2163 R_PurgeTexture(s->stain );s->stain = NULL;
2164 R_PurgeTexture(s->merged);s->merged = NULL;
2165 R_PurgeTexture(s->base );s->base = NULL;
2166 R_PurgeTexture(s->pants );s->pants = NULL;
2167 R_PurgeTexture(s->shirt );s->shirt = NULL;
2168 R_PurgeTexture(s->nmap );s->nmap = NULL;
2169 R_PurgeTexture(s->gloss );s->gloss = NULL;
2170 R_PurgeTexture(s->glow );s->glow = NULL;
2171 R_PurgeTexture(s->fog );s->fog = NULL;
2172 s->loadsequence = 0;
2178 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
2180 char basename[MAX_QPATH];
2182 Image_StripImageExtension(name, basename, sizeof(basename));
2184 if( last == NULL ) {
2186 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2187 item = r_skinframe.hash[hashindex];
2192 // linearly search through the hash bucket
2193 for( ; item ; item = item->next ) {
2194 if( !strcmp( item->basename, basename ) ) {
2201 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
2205 char basename[MAX_QPATH];
2207 Image_StripImageExtension(name, basename, sizeof(basename));
2209 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
2210 for (item = r_skinframe.hash[hashindex];item;item = item->next)
2211 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
2215 rtexture_t *dyntexture;
2216 // check whether its a dynamic texture
2217 dyntexture = CL_GetDynTexture( basename );
2218 if (!add && !dyntexture)
2220 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
2221 memset(item, 0, sizeof(*item));
2222 strlcpy(item->basename, basename, sizeof(item->basename));
2223 item->base = dyntexture; // either NULL or dyntexture handle
2224 item->textureflags = textureflags;
2225 item->comparewidth = comparewidth;
2226 item->compareheight = compareheight;
2227 item->comparecrc = comparecrc;
2228 item->next = r_skinframe.hash[hashindex];
2229 r_skinframe.hash[hashindex] = item;
2231 else if( item->base == NULL )
2233 rtexture_t *dyntexture;
2234 // check whether its a dynamic texture
2235 // 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]
2236 dyntexture = CL_GetDynTexture( basename );
2237 item->base = dyntexture; // either NULL or dyntexture handle
2240 R_SkinFrame_MarkUsed(item);
2244 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
2246 unsigned long long avgcolor[5], wsum; \
2254 for(pix = 0; pix < cnt; ++pix) \
2257 for(comp = 0; comp < 3; ++comp) \
2259 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
2262 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2264 for(comp = 0; comp < 3; ++comp) \
2265 avgcolor[comp] += getpixel * w; \
2268 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
2269 avgcolor[4] += getpixel; \
2271 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
2273 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
2274 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
2275 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
2276 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
2279 skinframe_t *R_SkinFrame_LoadExternal_CheckAlpha(const char *name, int textureflags, qboolean complain, qboolean *has_alpha)
2281 // FIXME: it should be possible to disable loading various layers using
2282 // cvars, to prevent wasted loading time and memory usage if the user does
2284 qboolean loadnormalmap = true;
2285 qboolean loadgloss = true;
2286 qboolean loadpantsandshirt = true;
2287 qboolean loadglow = true;
2289 unsigned char *pixels;
2290 unsigned char *bumppixels;
2291 unsigned char *basepixels = NULL;
2292 int basepixels_width;
2293 int basepixels_height;
2294 skinframe_t *skinframe;
2298 if (cls.state == ca_dedicated)
2301 // return an existing skinframe if already loaded
2302 // if loading of the first image fails, don't make a new skinframe as it
2303 // would cause all future lookups of this to be missing
2304 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
2305 if (skinframe && skinframe->base)
2308 basepixels = loadimagepixelsbgra(name, complain, true);
2309 if (basepixels == NULL)
2312 if (developer_loading.integer)
2313 Con_Printf("loading skin \"%s\"\n", name);
2315 // we've got some pixels to store, so really allocate this new texture now
2317 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
2318 skinframe->stain = NULL;
2319 skinframe->merged = NULL;
2320 skinframe->base = r_texture_notexture;
2321 skinframe->pants = NULL;
2322 skinframe->shirt = NULL;
2323 skinframe->nmap = r_texture_blanknormalmap;
2324 skinframe->gloss = NULL;
2325 skinframe->glow = NULL;
2326 skinframe->fog = NULL;
2328 basepixels_width = image_width;
2329 basepixels_height = image_height;
2330 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);
2332 if (textureflags & TEXF_ALPHA)
2334 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
2335 if (basepixels[j] < 255)
2337 if (j < basepixels_width * basepixels_height * 4)
2339 // has transparent pixels
2341 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2342 for (j = 0;j < image_width * image_height * 4;j += 4)
2347 pixels[j+3] = basepixels[j+3];
2349 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);
2354 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
2355 //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]);
2357 // _norm is the name used by tenebrae and has been adopted as standard
2360 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
2362 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);
2366 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
2368 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
2369 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
2370 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);
2372 Mem_Free(bumppixels);
2374 else if (r_shadow_bumpscale_basetexture.value > 0)
2376 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
2377 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
2378 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);
2382 // _luma is supported for tenebrae compatibility
2383 // (I think it's a very stupid name, but oh well)
2384 // _glow is the preferred name
2385 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;}
2386 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;}
2387 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;}
2388 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;}
2391 Mem_Free(basepixels);
2396 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
2399 return R_SkinFrame_LoadExternal_CheckAlpha(name, textureflags, complain, &has_alpha);
2402 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)
2407 for (i = 0;i < width*height;i++)
2408 if (((unsigned char *)&palette[in[i]])[3] > 0)
2410 if (i == width*height)
2413 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
2416 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
2417 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
2420 unsigned char *temp1, *temp2;
2421 skinframe_t *skinframe;
2423 if (cls.state == ca_dedicated)
2426 // if already loaded just return it, otherwise make a new skinframe
2427 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
2428 if (skinframe && skinframe->base)
2431 skinframe->stain = NULL;
2432 skinframe->merged = NULL;
2433 skinframe->base = r_texture_notexture;
2434 skinframe->pants = NULL;
2435 skinframe->shirt = NULL;
2436 skinframe->nmap = r_texture_blanknormalmap;
2437 skinframe->gloss = NULL;
2438 skinframe->glow = NULL;
2439 skinframe->fog = NULL;
2441 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2445 if (developer_loading.integer)
2446 Con_Printf("loading 32bit skin \"%s\"\n", name);
2448 if (r_shadow_bumpscale_basetexture.value > 0)
2450 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2451 temp2 = temp1 + width * height * 4;
2452 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2453 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2456 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2457 if (textureflags & TEXF_ALPHA)
2459 for (i = 3;i < width * height * 4;i += 4)
2460 if (skindata[i] < 255)
2462 if (i < width * height * 4)
2464 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2465 memcpy(fogpixels, skindata, width * height * 4);
2466 for (i = 0;i < width * height * 4;i += 4)
2467 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2468 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2469 Mem_Free(fogpixels);
2473 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
2474 //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]);
2479 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2482 unsigned char *temp1, *temp2;
2483 unsigned int *palette;
2484 skinframe_t *skinframe;
2486 if (cls.state == ca_dedicated)
2489 // if already loaded just return it, otherwise make a new skinframe
2490 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2491 if (skinframe && skinframe->base)
2494 palette = (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete));
2496 skinframe->stain = NULL;
2497 skinframe->merged = NULL;
2498 skinframe->base = r_texture_notexture;
2499 skinframe->pants = NULL;
2500 skinframe->shirt = NULL;
2501 skinframe->nmap = r_texture_blanknormalmap;
2502 skinframe->gloss = NULL;
2503 skinframe->glow = NULL;
2504 skinframe->fog = NULL;
2506 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2510 if (developer_loading.integer)
2511 Con_Printf("loading quake skin \"%s\"\n", name);
2513 if (r_shadow_bumpscale_basetexture.value > 0)
2515 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2516 temp2 = temp1 + width * height * 4;
2517 // use either a custom palette or the quake palette
2518 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2519 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2520 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2523 // use either a custom palette, or the quake palette
2524 skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), palette, skinframe->textureflags, true); // all
2525 if (loadglowtexture)
2526 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2527 if (loadpantsandshirt)
2529 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2530 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2532 if (skinframe->pants || skinframe->shirt)
2533 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
2534 if (textureflags & TEXF_ALPHA)
2536 for (i = 0;i < width * height;i++)
2537 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2539 if (i < width * height)
2540 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2543 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
2544 //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]);
2549 skinframe_t *R_SkinFrame_LoadMissing(void)
2551 skinframe_t *skinframe;
2553 if (cls.state == ca_dedicated)
2556 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE | TEXF_FORCENEAREST, 0, 0, 0, true);
2557 skinframe->stain = NULL;
2558 skinframe->merged = NULL;
2559 skinframe->base = r_texture_notexture;
2560 skinframe->pants = NULL;
2561 skinframe->shirt = NULL;
2562 skinframe->nmap = r_texture_blanknormalmap;
2563 skinframe->gloss = NULL;
2564 skinframe->glow = NULL;
2565 skinframe->fog = NULL;
2567 skinframe->avgcolor[0] = rand() / RAND_MAX;
2568 skinframe->avgcolor[1] = rand() / RAND_MAX;
2569 skinframe->avgcolor[2] = rand() / RAND_MAX;
2570 skinframe->avgcolor[3] = 1;
2575 void gl_main_start(void)
2579 memset(r_queries, 0, sizeof(r_queries));
2581 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2582 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2584 // set up r_skinframe loading system for textures
2585 memset(&r_skinframe, 0, sizeof(r_skinframe));
2586 r_skinframe.loadsequence = 1;
2587 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2589 r_main_texturepool = R_AllocTexturePool();
2590 R_BuildBlankTextures();
2592 if (gl_texturecubemap)
2595 R_BuildNormalizationCube();
2597 r_texture_fogattenuation = NULL;
2598 r_texture_gammaramps = NULL;
2599 //r_texture_fogintensity = NULL;
2600 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2601 memset(&r_waterstate, 0, sizeof(r_waterstate));
2602 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2603 memset(&r_svbsp, 0, sizeof (r_svbsp));
2605 r_refdef.fogmasktable_density = 0;
2608 extern rtexture_t *loadingscreentexture;
2609 void gl_main_shutdown(void)
2612 qglDeleteQueriesARB(r_maxqueries, r_queries);
2616 memset(r_queries, 0, sizeof(r_queries));
2618 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2619 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2621 // clear out the r_skinframe state
2622 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2623 memset(&r_skinframe, 0, sizeof(r_skinframe));
2626 Mem_Free(r_svbsp.nodes);
2627 memset(&r_svbsp, 0, sizeof (r_svbsp));
2628 R_FreeTexturePool(&r_main_texturepool);
2629 loadingscreentexture = NULL;
2630 r_texture_blanknormalmap = NULL;
2631 r_texture_white = NULL;
2632 r_texture_grey128 = NULL;
2633 r_texture_black = NULL;
2634 r_texture_whitecube = NULL;
2635 r_texture_normalizationcube = NULL;
2636 r_texture_fogattenuation = NULL;
2637 r_texture_gammaramps = NULL;
2638 //r_texture_fogintensity = NULL;
2639 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2640 memset(&r_waterstate, 0, sizeof(r_waterstate));
2644 extern void CL_ParseEntityLump(char *entitystring);
2645 void gl_main_newmap(void)
2647 // FIXME: move this code to client
2649 char *entities, entname[MAX_QPATH];
2652 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2653 l = (int)strlen(entname) - 4;
2654 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2656 memcpy(entname + l, ".ent", 5);
2657 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2659 CL_ParseEntityLump(entities);
2664 if (cl.worldmodel->brush.entities)
2665 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2669 void GL_Main_Init(void)
2671 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2673 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2674 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2675 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2676 if (gamemode == GAME_NEHAHRA)
2678 Cvar_RegisterVariable (&gl_fogenable);
2679 Cvar_RegisterVariable (&gl_fogdensity);
2680 Cvar_RegisterVariable (&gl_fogred);
2681 Cvar_RegisterVariable (&gl_foggreen);
2682 Cvar_RegisterVariable (&gl_fogblue);
2683 Cvar_RegisterVariable (&gl_fogstart);
2684 Cvar_RegisterVariable (&gl_fogend);
2685 Cvar_RegisterVariable (&gl_skyclip);
2687 Cvar_RegisterVariable(&r_motionblur);
2688 Cvar_RegisterVariable(&r_motionblur_maxblur);
2689 Cvar_RegisterVariable(&r_motionblur_bmin);
2690 Cvar_RegisterVariable(&r_motionblur_vmin);
2691 Cvar_RegisterVariable(&r_motionblur_vmax);
2692 Cvar_RegisterVariable(&r_motionblur_vcoeff);
2693 Cvar_RegisterVariable(&r_motionblur_randomize);
2694 Cvar_RegisterVariable(&r_damageblur);
2695 Cvar_RegisterVariable(&r_animcache);
2696 Cvar_RegisterVariable(&r_depthfirst);
2697 Cvar_RegisterVariable(&r_useinfinitefarclip);
2698 Cvar_RegisterVariable(&r_nearclip);
2699 Cvar_RegisterVariable(&r_showbboxes);
2700 Cvar_RegisterVariable(&r_showsurfaces);
2701 Cvar_RegisterVariable(&r_showtris);
2702 Cvar_RegisterVariable(&r_shownormals);
2703 Cvar_RegisterVariable(&r_showlighting);
2704 Cvar_RegisterVariable(&r_showshadowvolumes);
2705 Cvar_RegisterVariable(&r_showcollisionbrushes);
2706 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2707 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2708 Cvar_RegisterVariable(&r_showdisabledepthtest);
2709 Cvar_RegisterVariable(&r_drawportals);
2710 Cvar_RegisterVariable(&r_drawentities);
2711 Cvar_RegisterVariable(&r_cullentities_trace);
2712 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2713 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2714 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2715 Cvar_RegisterVariable(&r_drawviewmodel);
2716 Cvar_RegisterVariable(&r_speeds);
2717 Cvar_RegisterVariable(&r_fullbrights);
2718 Cvar_RegisterVariable(&r_wateralpha);
2719 Cvar_RegisterVariable(&r_dynamic);
2720 Cvar_RegisterVariable(&r_fullbright);
2721 Cvar_RegisterVariable(&r_shadows);
2722 Cvar_RegisterVariable(&r_shadows_darken);
2723 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
2724 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
2725 Cvar_RegisterVariable(&r_shadows_throwdistance);
2726 Cvar_RegisterVariable(&r_shadows_throwdirection);
2727 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2728 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2729 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2730 Cvar_RegisterVariable(&r_fog_exp2);
2731 Cvar_RegisterVariable(&r_drawfog);
2732 Cvar_RegisterVariable(&r_textureunits);
2733 Cvar_RegisterVariable(&r_glsl);
2734 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2735 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2736 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2737 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2738 Cvar_RegisterVariable(&r_glsl_postprocess);
2739 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
2740 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
2741 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
2742 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
2743 Cvar_RegisterVariable(&r_glsl_usegeneric);
2744 Cvar_RegisterVariable(&r_water);
2745 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2746 Cvar_RegisterVariable(&r_water_clippingplanebias);
2747 Cvar_RegisterVariable(&r_water_refractdistort);
2748 Cvar_RegisterVariable(&r_water_reflectdistort);
2749 Cvar_RegisterVariable(&r_lerpsprites);
2750 Cvar_RegisterVariable(&r_lerpmodels);
2751 Cvar_RegisterVariable(&r_lerplightstyles);
2752 Cvar_RegisterVariable(&r_waterscroll);
2753 Cvar_RegisterVariable(&r_bloom);
2754 Cvar_RegisterVariable(&r_bloom_colorscale);
2755 Cvar_RegisterVariable(&r_bloom_brighten);
2756 Cvar_RegisterVariable(&r_bloom_blur);
2757 Cvar_RegisterVariable(&r_bloom_resolution);
2758 Cvar_RegisterVariable(&r_bloom_colorexponent);
2759 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2760 Cvar_RegisterVariable(&r_hdr);
2761 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2762 Cvar_RegisterVariable(&r_hdr_glowintensity);
2763 Cvar_RegisterVariable(&r_hdr_range);
2764 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2765 Cvar_RegisterVariable(&developer_texturelogging);
2766 Cvar_RegisterVariable(&gl_lightmaps);
2767 Cvar_RegisterVariable(&r_test);
2768 Cvar_RegisterVariable(&r_batchmode);
2769 Cvar_RegisterVariable(&r_glsl_saturation);
2770 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2771 Cvar_SetValue("r_fullbrights", 0);
2772 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2774 Cvar_RegisterVariable(&r_track_sprites);
2775 Cvar_RegisterVariable(&r_track_sprites_flags);
2776 Cvar_RegisterVariable(&r_track_sprites_scalew);
2777 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2780 extern void R_Textures_Init(void);
2781 extern void GL_Draw_Init(void);
2782 extern void GL_Main_Init(void);
2783 extern void R_Shadow_Init(void);
2784 extern void R_Sky_Init(void);
2785 extern void GL_Surf_Init(void);
2786 extern void R_Particles_Init(void);
2787 extern void R_Explosion_Init(void);
2788 extern void gl_backend_init(void);
2789 extern void Sbar_Init(void);
2790 extern void R_LightningBeams_Init(void);
2791 extern void Mod_RenderInit(void);
2793 void Render_Init(void)
2805 R_LightningBeams_Init();
2814 extern char *ENGINE_EXTENSIONS;
2817 gl_renderer = (const char *)qglGetString(GL_RENDERER);
2818 gl_vendor = (const char *)qglGetString(GL_VENDOR);
2819 gl_version = (const char *)qglGetString(GL_VERSION);
2820 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
2824 if (!gl_platformextensions)
2825 gl_platformextensions = "";
2827 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
2828 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
2829 Con_Printf("GL_VERSION: %s\n", gl_version);
2830 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
2831 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
2833 VID_CheckExtensions();
2835 // LordHavoc: report supported extensions
2836 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2838 // clear to black (loading plaque will be seen over this)
2840 qglClearColor(0,0,0,1);CHECKGLERROR
2841 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2844 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2848 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2850 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2853 p = r_refdef.view.frustum + i;
2858 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2862 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2866 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2870 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2874 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2878 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2882 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2886 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2894 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2898 for (i = 0;i < numplanes;i++)
2905 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2909 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2913 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2917 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2921 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2925 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2929 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2933 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2941 //==================================================================================
2943 // LordHavoc: animcache written by Echon, refactored and reformatted by me
2946 * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
2947 * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
2948 * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
2951 typedef struct r_animcache_entity_s
2958 qboolean wantnormals;
2959 qboolean wanttangents;
2961 r_animcache_entity_t;
2963 typedef struct r_animcache_s
2965 r_animcache_entity_t entity[MAX_EDICTS*2];
2971 static r_animcache_t r_animcachestate;
2973 void R_AnimCache_Free(void)
2976 for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
2978 r_animcachestate.entity[idx].maxvertices = 0;
2979 Mem_Free(r_animcachestate.entity[idx].vertex3f);
2980 r_animcachestate.entity[idx].vertex3f = NULL;
2981 r_animcachestate.entity[idx].normal3f = NULL;
2982 r_animcachestate.entity[idx].svector3f = NULL;
2983 r_animcachestate.entity[idx].tvector3f = NULL;
2985 r_animcachestate.currentindex = 0;
2986 r_animcachestate.maxindex = 0;
2989 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
2993 r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
2995 if (cache->maxvertices >= numvertices)
2998 // Release existing memory
2999 if (cache->vertex3f)
3000 Mem_Free(cache->vertex3f);
3002 // Pad by 1024 verts
3003 cache->maxvertices = (numvertices + 1023) & ~1023;
3004 arraySize = cache->maxvertices * 3;
3006 // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3007 base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3008 r_animcachestate.entity[cacheIdx].vertex3f = base;
3009 r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3010 r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3011 r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3013 // Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3016 void R_AnimCache_NewFrame(void)
3020 if (r_animcache.integer && r_drawentities.integer)
3021 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3022 else if (r_animcachestate.maxindex)
3025 r_animcachestate.currentindex = 0;
3027 for (i = 0;i < r_refdef.scene.numentities;i++)
3028 r_refdef.scene.entities[i]->animcacheindex = -1;
3031 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3033 dp_model_t *model = ent->model;
3034 r_animcache_entity_t *c;
3035 // see if it's already cached this frame
3036 if (ent->animcacheindex >= 0)
3038 // add normals/tangents if needed
3039 c = r_animcachestate.entity + ent->animcacheindex;
3041 wantnormals = false;
3042 if (c->wanttangents)
3043 wanttangents = false;
3044 if (wantnormals || wanttangents)
3045 model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3049 // see if this ent is worth caching
3050 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3052 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3054 // assign it a cache entry and make sure the arrays are big enough
3055 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3056 ent->animcacheindex = r_animcachestate.currentindex++;
3057 c = r_animcachestate.entity + ent->animcacheindex;
3058 c->wantnormals = wantnormals;
3059 c->wanttangents = wanttangents;
3060 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3065 void R_AnimCache_CacheVisibleEntities(void)
3068 qboolean wantnormals;
3069 qboolean wanttangents;
3071 if (!r_animcachestate.maxindex)
3074 wantnormals = !r_showsurfaces.integer;
3075 wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3077 // TODO: thread this?
3079 for (i = 0;i < r_refdef.scene.numentities;i++)
3081 if (!r_refdef.viewcache.entityvisible[i])
3083 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3087 //==================================================================================
3089 static void R_View_UpdateEntityLighting (void)
3092 entity_render_t *ent;
3093 vec3_t tempdiffusenormal;
3095 for (i = 0;i < r_refdef.scene.numentities;i++)
3097 ent = r_refdef.scene.entities[i];
3099 // skip unseen models
3100 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3104 if (ent->model && ent->model->brush.num_leafs)
3106 // TODO: use modellight for r_ambient settings on world?
3107 VectorSet(ent->modellight_ambient, 0, 0, 0);
3108 VectorSet(ent->modellight_diffuse, 0, 0, 0);
3109 VectorSet(ent->modellight_lightdir, 0, 0, 1);
3113 // fetch the lighting from the worldmodel data
3114 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));
3115 VectorClear(ent->modellight_diffuse);
3116 VectorClear(tempdiffusenormal);
3117 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3120 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3121 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3124 VectorSet(ent->modellight_ambient, 1, 1, 1);
3126 // move the light direction into modelspace coordinates for lighting code
3127 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3128 if(VectorLength2(ent->modellight_lightdir) == 0)
3129 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3130 VectorNormalize(ent->modellight_lightdir);
3134 static void R_View_UpdateEntityVisible (void)
3137 entity_render_t *ent;
3139 if (!r_drawentities.integer)
3142 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3143 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3145 // worldmodel can check visibility
3146 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3147 for (i = 0;i < r_refdef.scene.numentities;i++)
3149 ent = r_refdef.scene.entities[i];
3150 if (!(ent->flags & renderimask))
3151 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)))
3152 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))
3153 r_refdef.viewcache.entityvisible[i] = true;
3155 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3157 for (i = 0;i < r_refdef.scene.numentities;i++)
3159 ent = r_refdef.scene.entities[i];
3160 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
3162 if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.scene.worldmodel, r_refdef.view.origin, ent->mins, ent->maxs))
3163 ent->last_trace_visibility = realtime;
3164 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3165 r_refdef.viewcache.entityvisible[i] = 0;
3172 // no worldmodel or it can't check visibility
3173 for (i = 0;i < r_refdef.scene.numentities;i++)
3175 ent = r_refdef.scene.entities[i];
3176 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));
3181 /// only used if skyrendermasked, and normally returns false
3182 int R_DrawBrushModelsSky (void)
3185 entity_render_t *ent;
3187 if (!r_drawentities.integer)
3191 for (i = 0;i < r_refdef.scene.numentities;i++)
3193 if (!r_refdef.viewcache.entityvisible[i])
3195 ent = r_refdef.scene.entities[i];
3196 if (!ent->model || !ent->model->DrawSky)
3198 ent->model->DrawSky(ent);
3204 static void R_DrawNoModel(entity_render_t *ent);
3205 static void R_DrawModels(void)
3208 entity_render_t *ent;
3210 if (!r_drawentities.integer)
3213 for (i = 0;i < r_refdef.scene.numentities;i++)
3215 if (!r_refdef.viewcache.entityvisible[i])
3217 ent = r_refdef.scene.entities[i];
3218 r_refdef.stats.entities++;
3219 if (ent->model && ent->model->Draw != NULL)
3220 ent->model->Draw(ent);
3226 static void R_DrawModelsDepth(void)
3229 entity_render_t *ent;
3231 if (!r_drawentities.integer)
3234 for (i = 0;i < r_refdef.scene.numentities;i++)
3236 if (!r_refdef.viewcache.entityvisible[i])
3238 ent = r_refdef.scene.entities[i];
3239 if (ent->model && ent->model->DrawDepth != NULL)
3240 ent->model->DrawDepth(ent);
3244 static void R_DrawModelsDebug(void)
3247 entity_render_t *ent;
3249 if (!r_drawentities.integer)
3252 for (i = 0;i < r_refdef.scene.numentities;i++)
3254 if (!r_refdef.viewcache.entityvisible[i])
3256 ent = r_refdef.scene.entities[i];
3257 if (ent->model && ent->model->DrawDebug != NULL)
3258 ent->model->DrawDebug(ent);
3262 static void R_DrawModelsAddWaterPlanes(void)
3265 entity_render_t *ent;
3267 if (!r_drawentities.integer)
3270 for (i = 0;i < r_refdef.scene.numentities;i++)
3272 if (!r_refdef.viewcache.entityvisible[i])
3274 ent = r_refdef.scene.entities[i];
3275 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3276 ent->model->DrawAddWaterPlanes(ent);
3280 static void R_View_SetFrustum(void)
3283 double slopex, slopey;
3284 vec3_t forward, left, up, origin;
3286 // we can't trust r_refdef.view.forward and friends in reflected scenes
3287 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3290 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3291 r_refdef.view.frustum[0].normal[1] = 0 - 0;
3292 r_refdef.view.frustum[0].normal[2] = -1 - 0;
3293 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3294 r_refdef.view.frustum[1].normal[1] = 0 + 0;
3295 r_refdef.view.frustum[1].normal[2] = -1 + 0;
3296 r_refdef.view.frustum[2].normal[0] = 0 - 0;
3297 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3298 r_refdef.view.frustum[2].normal[2] = -1 - 0;
3299 r_refdef.view.frustum[3].normal[0] = 0 + 0;
3300 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3301 r_refdef.view.frustum[3].normal[2] = -1 + 0;
3305 zNear = r_refdef.nearclip;
3306 nudge = 1.0 - 1.0 / (1<<23);
3307 r_refdef.view.frustum[4].normal[0] = 0 - 0;
3308 r_refdef.view.frustum[4].normal[1] = 0 - 0;
3309 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3310 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3311 r_refdef.view.frustum[5].normal[0] = 0 + 0;
3312 r_refdef.view.frustum[5].normal[1] = 0 + 0;
3313 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3314 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3320 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3321 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3322 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3323 r_refdef.view.frustum[0].dist = m[15] - m[12];
3325 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3326 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3327 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3328 r_refdef.view.frustum[1].dist = m[15] + m[12];
3330 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3331 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3332 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3333 r_refdef.view.frustum[2].dist = m[15] - m[13];
3335 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3336 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3337 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3338 r_refdef.view.frustum[3].dist = m[15] + m[13];
3340 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3341 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3342 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3343 r_refdef.view.frustum[4].dist = m[15] - m[14];
3345 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3346 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3347 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3348 r_refdef.view.frustum[5].dist = m[15] + m[14];
3351 if (r_refdef.view.useperspective)
3353 slopex = 1.0 / r_refdef.view.frustum_x;
3354 slopey = 1.0 / r_refdef.view.frustum_y;
3355 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3356 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
3357 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
3358 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
3359 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3361 // Leaving those out was a mistake, those were in the old code, and they
3362 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3363 // I couldn't reproduce it after adding those normalizations. --blub
3364 VectorNormalize(r_refdef.view.frustum[0].normal);
3365 VectorNormalize(r_refdef.view.frustum[1].normal);
3366 VectorNormalize(r_refdef.view.frustum[2].normal);
3367 VectorNormalize(r_refdef.view.frustum[3].normal);
3369 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3370 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]);
3371 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]);
3372 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]);
3373 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]);
3375 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3376 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3377 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3378 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3379 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3383 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3384 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3385 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3386 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3387 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3388 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3389 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3390 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3391 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3392 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3394 r_refdef.view.numfrustumplanes = 5;
3396 if (r_refdef.view.useclipplane)
3398 r_refdef.view.numfrustumplanes = 6;
3399 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3402 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3403 PlaneClassify(r_refdef.view.frustum + i);
3405 // LordHavoc: note to all quake engine coders, Quake had a special case
3406 // for 90 degrees which assumed a square view (wrong), so I removed it,
3407 // Quake2 has it disabled as well.
3409 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3410 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3411 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3412 //PlaneClassify(&frustum[0]);
3414 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3415 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3416 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3417 //PlaneClassify(&frustum[1]);
3419 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3420 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3421 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3422 //PlaneClassify(&frustum[2]);
3424 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3425 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3426 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3427 //PlaneClassify(&frustum[3]);
3430 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3431 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3432 //PlaneClassify(&frustum[4]);
3435 void R_View_Update(void)
3437 R_View_SetFrustum();
3438 R_View_WorldVisibility(r_refdef.view.useclipplane);
3439 R_View_UpdateEntityVisible();
3440 R_View_UpdateEntityLighting();
3443 void R_SetupView(qboolean allowwaterclippingplane)
3445 const double *customclipplane = NULL;
3447 if (r_refdef.view.useclipplane && allowwaterclippingplane)
3449 // LordHavoc: couldn't figure out how to make this approach the
3450 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3451 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3452 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3453 dist = r_refdef.view.clipplane.dist;
3454 plane[0] = r_refdef.view.clipplane.normal[0];
3455 plane[1] = r_refdef.view.clipplane.normal[1];
3456 plane[2] = r_refdef.view.clipplane.normal[2];
3458 customclipplane = plane;
3461 if (!r_refdef.view.useperspective)
3462 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);
3463 else if (gl_stencil && r_useinfinitefarclip.integer)
3464 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);
3466 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);
3467 R_SetViewport(&r_refdef.view.viewport);
3470 void R_ResetViewRendering2D(void)
3472 r_viewport_t viewport;
3475 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3476 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);
3477 R_SetViewport(&viewport);
3478 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3479 GL_Color(1, 1, 1, 1);
3480 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3481 GL_BlendFunc(GL_ONE, GL_ZERO);
3482 GL_AlphaTest(false);
3483 GL_ScissorTest(false);
3484 GL_DepthMask(false);
3485 GL_DepthRange(0, 1);
3486 GL_DepthTest(false);
3487 R_Mesh_Matrix(&identitymatrix);
3488 R_Mesh_ResetTextureState();
3489 GL_PolygonOffset(0, 0);
3490 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3491 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3492 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3493 qglStencilMask(~0);CHECKGLERROR
3494 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3495 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3496 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3497 R_SetupGenericShader(true);
3500 void R_ResetViewRendering3D(void)
3505 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3506 GL_Color(1, 1, 1, 1);
3507 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3508 GL_BlendFunc(GL_ONE, GL_ZERO);
3509 GL_AlphaTest(false);
3510 GL_ScissorTest(true);
3512 GL_DepthRange(0, 1);
3514 R_Mesh_Matrix(&identitymatrix);
3515 R_Mesh_ResetTextureState();
3516 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3517 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3518 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3519 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3520 qglStencilMask(~0);CHECKGLERROR
3521 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3522 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3523 GL_CullFace(r_refdef.view.cullface_back);
3524 R_SetupGenericShader(true);
3527 void R_RenderScene(void);
3528 void R_RenderWaterPlanes(void);
3530 static void R_Water_StartFrame(void)
3533 int waterwidth, waterheight, texturewidth, textureheight;
3534 r_waterstate_waterplane_t *p;
3536 // set waterwidth and waterheight to the water resolution that will be
3537 // used (often less than the screen resolution for faster rendering)
3538 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3539 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3541 // calculate desired texture sizes
3542 // can't use water if the card does not support the texture size
3543 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3544 texturewidth = textureheight = waterwidth = waterheight = 0;
3545 else if (gl_support_arb_texture_non_power_of_two)
3547 texturewidth = waterwidth;
3548 textureheight = waterheight;
3552 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
3553 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
3556 // allocate textures as needed
3557 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
3559 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3560 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
3562 if (p->texture_refraction)
3563 R_FreeTexture(p->texture_refraction);
3564 p->texture_refraction = NULL;
3565 if (p->texture_reflection)
3566 R_FreeTexture(p->texture_reflection);
3567 p->texture_reflection = NULL;
3569 memset(&r_waterstate, 0, sizeof(r_waterstate));
3570 r_waterstate.waterwidth = waterwidth;
3571 r_waterstate.waterheight = waterheight;
3572 r_waterstate.texturewidth = texturewidth;
3573 r_waterstate.textureheight = textureheight;
3576 // when doing a reduced render (HDR) we want to use a smaller area
3577 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
3578 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
3580 if (r_waterstate.waterwidth)
3582 r_waterstate.enabled = true;
3584 // set up variables that will be used in shader setup
3585 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3586 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
3587 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
3588 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
3591 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
3592 r_waterstate.numwaterplanes = 0;
3595 void R_Water_AddWaterPlane(msurface_t *surface)
3597 int triangleindex, planeindex;
3603 r_waterstate_waterplane_t *p;
3604 texture_t *t = R_GetCurrentTexture(surface->texture);
3605 // just use the first triangle with a valid normal for any decisions
3606 VectorClear(normal);
3607 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
3609 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
3610 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
3611 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
3612 TriangleNormal(vert[0], vert[1], vert[2], normal);
3613 if (VectorLength2(normal) >= 0.001)
3617 VectorCopy(normal, plane.normal);
3618 VectorNormalize(plane.normal);
3619 plane.dist = DotProduct(vert[0], plane.normal);
3620 PlaneClassify(&plane);
3621 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
3623 // skip backfaces (except if nocullface is set)
3624 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
3626 VectorNegate(plane.normal, plane.normal);
3628 PlaneClassify(&plane);
3632 // find a matching plane if there is one
3633 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3634 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
3636 if (planeindex >= r_waterstate.maxwaterplanes)
3637 return; // nothing we can do, out of planes
3639 // if this triangle does not fit any known plane rendered this frame, add one
3640 if (planeindex >= r_waterstate.numwaterplanes)
3642 // store the new plane
3643 r_waterstate.numwaterplanes++;
3645 // clear materialflags and pvs
3646 p->materialflags = 0;
3647 p->pvsvalid = false;
3649 // merge this surface's materialflags into the waterplane
3650 p->materialflags |= t->currentmaterialflags;
3651 // merge this surface's PVS into the waterplane
3652 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
3653 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
3654 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
3656 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
3661 static void R_Water_ProcessPlanes(void)
3663 r_refdef_view_t originalview;
3664 r_refdef_view_t myview;
3666 r_waterstate_waterplane_t *p;
3668 originalview = r_refdef.view;
3670 // make sure enough textures are allocated
3671 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3673 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3675 if (!p->texture_refraction)
3676 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);
3677 if (!p->texture_refraction)
3681 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3683 if (!p->texture_reflection)
3684 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);
3685 if (!p->texture_reflection)
3691 r_refdef.view = originalview;
3692 r_refdef.view.showdebug = false;
3693 r_refdef.view.width = r_waterstate.waterwidth;
3694 r_refdef.view.height = r_waterstate.waterheight;
3695 r_refdef.view.useclipplane = true;
3696 myview = r_refdef.view;
3697 r_waterstate.renderingscene = true;
3698 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
3700 // render the normal view scene and copy into texture
3701 // (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)
3702 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3704 r_refdef.view = myview;
3705 r_refdef.view.clipplane = p->plane;
3706 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3707 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3708 PlaneClassify(&r_refdef.view.clipplane);
3710 R_ResetViewRendering3D();
3711 R_ClearScreen(r_refdef.fogenabled);
3715 // copy view into the screen texture
3716 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3717 GL_ActiveTexture(0);
3719 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
3722 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3724 r_refdef.view = myview;
3725 // render reflected scene and copy into texture
3726 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3727 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3728 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3729 r_refdef.view.clipplane = p->plane;
3730 // reverse the cullface settings for this render
3731 r_refdef.view.cullface_front = GL_FRONT;
3732 r_refdef.view.cullface_back = GL_BACK;
3733 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3735 r_refdef.view.usecustompvs = true;
3737 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3739 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3742 R_ResetViewRendering3D();
3743 R_ClearScreen(r_refdef.fogenabled);
3747 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3748 GL_ActiveTexture(0);
3750 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
3753 r_waterstate.renderingscene = false;
3754 r_refdef.view = originalview;
3755 R_ResetViewRendering3D();
3756 R_ClearScreen(r_refdef.fogenabled);
3760 r_refdef.view = originalview;
3761 r_waterstate.renderingscene = false;
3762 Cvar_SetValueQuick(&r_water, 0);
3763 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3767 void R_Bloom_StartFrame(void)
3769 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3771 // set bloomwidth and bloomheight to the bloom resolution that will be
3772 // used (often less than the screen resolution for faster rendering)
3773 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
3774 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
3775 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
3776 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
3777 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
3779 // calculate desired texture sizes
3780 if (gl_support_arb_texture_non_power_of_two)
3782 screentexturewidth = r_refdef.view.width;
3783 screentextureheight = r_refdef.view.height;
3784 bloomtexturewidth = r_bloomstate.bloomwidth;
3785 bloomtextureheight = r_bloomstate.bloomheight;
3789 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3790 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3791 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3792 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3795 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))
3797 Cvar_SetValueQuick(&r_hdr, 0);
3798 Cvar_SetValueQuick(&r_bloom, 0);
3799 Cvar_SetValueQuick(&r_motionblur, 0);
3800 Cvar_SetValueQuick(&r_damageblur, 0);
3803 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)))
3804 screentexturewidth = screentextureheight = 0;
3805 if (!r_hdr.integer && !r_bloom.integer)
3806 bloomtexturewidth = bloomtextureheight = 0;
3808 // allocate textures as needed
3809 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3811 if (r_bloomstate.texture_screen)
3812 R_FreeTexture(r_bloomstate.texture_screen);
3813 r_bloomstate.texture_screen = NULL;
3814 r_bloomstate.screentexturewidth = screentexturewidth;
3815 r_bloomstate.screentextureheight = screentextureheight;
3816 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3817 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);
3819 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3821 if (r_bloomstate.texture_bloom)
3822 R_FreeTexture(r_bloomstate.texture_bloom);
3823 r_bloomstate.texture_bloom = NULL;
3824 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3825 r_bloomstate.bloomtextureheight = bloomtextureheight;
3826 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3827 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);
3830 // when doing a reduced render (HDR) we want to use a smaller area
3831 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
3832 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3833 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3834 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
3835 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
3837 // set up a texcoord array for the full resolution screen image
3838 // (we have to keep this around to copy back during final render)
3839 r_bloomstate.screentexcoord2f[0] = 0;
3840 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3841 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3842 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3843 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3844 r_bloomstate.screentexcoord2f[5] = 0;
3845 r_bloomstate.screentexcoord2f[6] = 0;
3846 r_bloomstate.screentexcoord2f[7] = 0;
3848 // set up a texcoord array for the reduced resolution bloom image
3849 // (which will be additive blended over the screen image)
3850 r_bloomstate.bloomtexcoord2f[0] = 0;
3851 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3852 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3853 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3854 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3855 r_bloomstate.bloomtexcoord2f[5] = 0;
3856 r_bloomstate.bloomtexcoord2f[6] = 0;
3857 r_bloomstate.bloomtexcoord2f[7] = 0;
3859 if (r_hdr.integer || r_bloom.integer)
3861 r_bloomstate.enabled = true;
3862 r_bloomstate.hdr = r_hdr.integer != 0;
3865 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);
3868 void R_Bloom_CopyBloomTexture(float colorscale)
3870 r_refdef.stats.bloom++;
3872 // scale down screen texture to the bloom texture size
3874 R_SetViewport(&r_bloomstate.viewport);
3875 GL_BlendFunc(GL_ONE, GL_ZERO);
3876 GL_Color(colorscale, colorscale, colorscale, 1);
3877 // TODO: optimize with multitexture or GLSL
3878 R_SetupGenericShader(true);
3879 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3880 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3881 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3882 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3884 // we now have a bloom image in the framebuffer
3885 // copy it into the bloom image texture for later processing
3886 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3887 GL_ActiveTexture(0);
3889 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
3890 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
3893 void R_Bloom_CopyHDRTexture(void)
3895 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3896 GL_ActiveTexture(0);
3898 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
3899 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
3902 void R_Bloom_MakeTexture(void)
3905 float xoffset, yoffset, r, brighten;
3907 r_refdef.stats.bloom++;
3909 R_ResetViewRendering2D();
3910 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3911 R_Mesh_ColorPointer(NULL, 0, 0);
3912 R_SetupGenericShader(true);
3914 // we have a bloom image in the framebuffer
3916 R_SetViewport(&r_bloomstate.viewport);
3918 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3921 r = bound(0, r_bloom_colorexponent.value / x, 1);
3922 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3923 GL_Color(r, r, r, 1);
3924 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3925 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3926 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3927 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3929 // copy the vertically blurred bloom view to a texture
3930 GL_ActiveTexture(0);
3932 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
3933 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
3936 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3937 brighten = r_bloom_brighten.value;
3939 brighten *= r_hdr_range.value;
3940 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3941 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3943 for (dir = 0;dir < 2;dir++)
3945 // blend on at multiple vertical offsets to achieve a vertical blur
3946 // TODO: do offset blends using GLSL
3947 GL_BlendFunc(GL_ONE, GL_ZERO);
3948 for (x = -range;x <= range;x++)
3950 if (!dir){xoffset = 0;yoffset = x;}
3951 else {xoffset = x;yoffset = 0;}
3952 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3953 yoffset /= (float)r_bloomstate.bloomtextureheight;
3954 // compute a texcoord array with the specified x and y offset
3955 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3956 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3957 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3958 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3959 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3960 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3961 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3962 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3963 // this r value looks like a 'dot' particle, fading sharply to
3964 // black at the edges
3965 // (probably not realistic but looks good enough)
3966 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3967 //r = (dir ? 1.0f : brighten)/(range*2+1);
3968 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3969 GL_Color(r, r, r, 1);
3970 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3971 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3972 GL_BlendFunc(GL_ONE, GL_ONE);
3975 // copy the vertically blurred bloom view to a texture
3976 GL_ActiveTexture(0);
3978 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
3979 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
3982 // apply subtract last
3983 // (just like it would be in a GLSL shader)
3984 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3986 GL_BlendFunc(GL_ONE, GL_ZERO);
3987 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3988 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3989 GL_Color(1, 1, 1, 1);
3990 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3991 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3993 GL_BlendFunc(GL_ONE, GL_ONE);
3994 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3995 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3996 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3997 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3998 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
3999 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4000 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4002 // copy the darkened bloom view to a texture
4003 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4004 GL_ActiveTexture(0);
4006 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4007 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4011 void R_HDR_RenderBloomTexture(void)
4013 int oldwidth, oldheight;
4014 float oldcolorscale;
4016 oldcolorscale = r_refdef.view.colorscale;
4017 oldwidth = r_refdef.view.width;
4018 oldheight = r_refdef.view.height;
4019 r_refdef.view.width = r_bloomstate.bloomwidth;
4020 r_refdef.view.height = r_bloomstate.bloomheight;
4022 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
4023 // TODO: add exposure compensation features
4024 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4026 r_refdef.view.showdebug = false;
4027 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4029 R_ResetViewRendering3D();
4031 R_ClearScreen(r_refdef.fogenabled);
4032 if (r_timereport_active)
4033 R_TimeReport("HDRclear");
4036 if (r_timereport_active)
4037 R_TimeReport("visibility");
4039 // only do secondary renders with HDR if r_hdr is 2 or higher
4040 r_waterstate.numwaterplanes = 0;
4041 if (r_waterstate.enabled && r_hdr.integer >= 2)
4042 R_RenderWaterPlanes();
4044 r_refdef.view.showdebug = true;
4046 r_waterstate.numwaterplanes = 0;
4048 R_ResetViewRendering2D();
4050 R_Bloom_CopyHDRTexture();
4051 R_Bloom_MakeTexture();
4053 // restore the view settings
4054 r_refdef.view.width = oldwidth;
4055 r_refdef.view.height = oldheight;
4056 r_refdef.view.colorscale = oldcolorscale;
4058 R_ResetViewRendering3D();
4060 R_ClearScreen(r_refdef.fogenabled);
4061 if (r_timereport_active)
4062 R_TimeReport("viewclear");
4065 static void R_BlendView(void)
4067 if (r_bloomstate.texture_screen)
4069 // make sure the buffer is available
4070 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4072 R_ResetViewRendering2D();
4073 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4074 R_Mesh_ColorPointer(NULL, 0, 0);
4075 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4076 GL_ActiveTexture(0);CHECKGLERROR
4078 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4080 // declare variables
4082 static float avgspeed;
4084 speed = VectorLength(cl.movement_velocity);
4086 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4087 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4089 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4090 speed = bound(0, speed, 1);
4091 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4093 // calculate values into a standard alpha
4094 cl.motionbluralpha = 1 - exp(-
4096 (r_motionblur.value * speed / 80)
4098 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4101 max(0.0001, cl.time - cl.oldtime) // fps independent
4104 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4105 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4107 if (cl.motionbluralpha > 0)
4109 R_SetupGenericShader(true);
4110 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4111 GL_Color(1, 1, 1, cl.motionbluralpha);
4112 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4113 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4114 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4115 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4119 // copy view into the screen texture
4120 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
4121 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4124 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4126 unsigned int permutation =
4127 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4128 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4129 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4130 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4131 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4133 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4135 // render simple bloom effect
4136 // copy the screen and shrink it and darken it for the bloom process
4137 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4138 // make the bloom texture
4139 R_Bloom_MakeTexture();
4142 R_ResetViewRendering2D();
4143 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4144 R_Mesh_ColorPointer(NULL, 0, 0);
4145 GL_Color(1, 1, 1, 1);
4146 GL_BlendFunc(GL_ONE, GL_ZERO);
4147 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4148 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4149 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4150 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4151 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4152 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4153 R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4154 if (r_glsl_permutation->loc_TintColor >= 0)
4155 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4156 if (r_glsl_permutation->loc_ClientTime >= 0)
4157 qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4158 if (r_glsl_permutation->loc_PixelSize >= 0)
4159 qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4160 if (r_glsl_permutation->loc_UserVec1 >= 0)
4162 float a=0, b=0, c=0, d=0;
4163 #if _MSC_VER >= 1400
4164 #define sscanf sscanf_s
4166 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4167 qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4169 if (r_glsl_permutation->loc_UserVec2 >= 0)
4171 float a=0, b=0, c=0, d=0;
4172 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4173 qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4175 if (r_glsl_permutation->loc_UserVec3 >= 0)
4177 float a=0, b=0, c=0, d=0;
4178 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4179 qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4181 if (r_glsl_permutation->loc_UserVec4 >= 0)
4183 float a=0, b=0, c=0, d=0;
4184 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4185 qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4187 if (r_glsl_permutation->loc_Saturation >= 0)
4188 qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4189 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4190 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4196 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4198 // render high dynamic range bloom effect
4199 // the bloom texture was made earlier this render, so we just need to
4200 // blend it onto the screen...
4201 R_ResetViewRendering2D();
4202 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4203 R_Mesh_ColorPointer(NULL, 0, 0);
4204 R_SetupGenericShader(true);
4205 GL_Color(1, 1, 1, 1);
4206 GL_BlendFunc(GL_ONE, GL_ONE);
4207 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4208 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4209 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4210 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4212 else if (r_bloomstate.texture_bloom)
4214 // render simple bloom effect
4215 // copy the screen and shrink it and darken it for the bloom process
4216 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4217 // make the bloom texture
4218 R_Bloom_MakeTexture();
4219 // put the original screen image back in place and blend the bloom
4221 R_ResetViewRendering2D();
4222 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4223 R_Mesh_ColorPointer(NULL, 0, 0);
4224 GL_Color(1, 1, 1, 1);
4225 GL_BlendFunc(GL_ONE, GL_ZERO);
4226 // do both in one pass if possible
4227 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4228 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4229 if (r_textureunits.integer >= 2 && gl_combine.integer)
4231 R_SetupGenericTwoTextureShader(GL_ADD);
4232 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4233 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4237 R_SetupGenericShader(true);
4238 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4239 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4240 // now blend on the bloom texture
4241 GL_BlendFunc(GL_ONE, GL_ONE);
4242 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4243 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4245 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4246 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4248 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4250 // apply a color tint to the whole view
4251 R_ResetViewRendering2D();
4252 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4253 R_Mesh_ColorPointer(NULL, 0, 0);
4254 R_SetupGenericShader(false);
4255 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4256 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4257 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
4261 matrix4x4_t r_waterscrollmatrix;
4263 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4265 if (r_refdef.fog_density)
4267 r_refdef.fogcolor[0] = r_refdef.fog_red;
4268 r_refdef.fogcolor[1] = r_refdef.fog_green;
4269 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4273 VectorCopy(r_refdef.fogcolor, fogvec);
4274 // color.rgb *= ContrastBoost * SceneBrightness;
4275 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4276 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4277 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4278 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4283 void R_UpdateVariables(void)
4287 r_refdef.scene.ambient = r_ambient.value;
4289 r_refdef.farclip = 4096;
4290 if (r_refdef.scene.worldmodel)
4291 r_refdef.farclip += r_refdef.scene.worldmodel->radius * 2;
4292 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4294 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4295 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4296 r_refdef.polygonfactor = 0;
4297 r_refdef.polygonoffset = 0;
4298 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4299 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4301 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4302 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4303 r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4304 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4305 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4306 if (r_showsurfaces.integer)
4308 r_refdef.scene.rtworld = false;
4309 r_refdef.scene.rtworldshadows = false;
4310 r_refdef.scene.rtdlight = false;
4311 r_refdef.scene.rtdlightshadows = false;
4312 r_refdef.lightmapintensity = 0;
4315 if (gamemode == GAME_NEHAHRA)
4317 if (gl_fogenable.integer)
4319 r_refdef.oldgl_fogenable = true;
4320 r_refdef.fog_density = gl_fogdensity.value;
4321 r_refdef.fog_red = gl_fogred.value;
4322 r_refdef.fog_green = gl_foggreen.value;
4323 r_refdef.fog_blue = gl_fogblue.value;
4324 r_refdef.fog_alpha = 1;
4325 r_refdef.fog_start = 0;
4326 r_refdef.fog_end = gl_skyclip.value;
4328 else if (r_refdef.oldgl_fogenable)
4330 r_refdef.oldgl_fogenable = false;
4331 r_refdef.fog_density = 0;
4332 r_refdef.fog_red = 0;
4333 r_refdef.fog_green = 0;
4334 r_refdef.fog_blue = 0;
4335 r_refdef.fog_alpha = 0;
4336 r_refdef.fog_start = 0;
4337 r_refdef.fog_end = 0;
4341 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4342 r_refdef.fog_start = max(0, r_refdef.fog_start);
4343 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4345 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4347 if (r_refdef.fog_density && r_drawfog.integer)
4349 r_refdef.fogenabled = true;
4350 // this is the point where the fog reaches 0.9986 alpha, which we
4351 // consider a good enough cutoff point for the texture
4352 // (0.9986 * 256 == 255.6)
4353 if (r_fog_exp2.integer)
4354 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4356 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4357 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4358 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4359 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4360 // fog color was already set
4361 // update the fog texture
4362 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)
4363 R_BuildFogTexture();
4366 r_refdef.fogenabled = false;
4368 if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4370 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4372 // build GLSL gamma texture
4373 #define RAMPWIDTH 256
4374 unsigned short ramp[RAMPWIDTH * 3];
4375 unsigned char rampbgr[RAMPWIDTH][4];
4378 r_texture_gammaramps_serial = vid_gammatables_serial;
4380 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4381 for(i = 0; i < RAMPWIDTH; ++i)
4383 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4384 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4385 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4388 if (r_texture_gammaramps)
4390 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4394 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);
4400 // remove GLSL gamma texture
4404 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4405 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4411 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4412 if( scenetype != r_currentscenetype ) {
4413 // store the old scenetype
4414 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4415 r_currentscenetype = scenetype;
4416 // move in the new scene
4417 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4426 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4428 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4429 if( scenetype == r_currentscenetype ) {
4430 return &r_refdef.scene;
4432 return &r_scenes_store[ scenetype ];
4441 void R_RenderView(void)
4443 if (r_timereport_active)
4444 R_TimeReport("start");
4445 r_frame++; // used only by R_GetCurrentTexture
4446 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4448 R_AnimCache_NewFrame();
4450 if (r_refdef.view.isoverlay)
4452 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4453 GL_Clear( GL_DEPTH_BUFFER_BIT );
4454 R_TimeReport("depthclear");
4456 r_refdef.view.showdebug = false;
4458 r_waterstate.enabled = false;
4459 r_waterstate.numwaterplanes = 0;
4467 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0/* || !r_refdef.scene.worldmodel*/)
4468 return; //Host_Error ("R_RenderView: NULL worldmodel");
4470 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4472 // break apart the view matrix into vectors for various purposes
4473 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4474 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4475 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4476 VectorNegate(r_refdef.view.left, r_refdef.view.right);
4477 // make an inverted copy of the view matrix for tracking sprites
4478 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4480 R_Shadow_UpdateWorldLightSelection();
4482 R_Bloom_StartFrame();
4483 R_Water_StartFrame();
4486 if (r_timereport_active)
4487 R_TimeReport("viewsetup");
4489 R_ResetViewRendering3D();
4491 if (r_refdef.view.clear || r_refdef.fogenabled)
4493 R_ClearScreen(r_refdef.fogenabled);
4494 if (r_timereport_active)
4495 R_TimeReport("viewclear");
4497 r_refdef.view.clear = true;
4499 // this produces a bloom texture to be used in R_BlendView() later
4501 R_HDR_RenderBloomTexture();
4503 r_refdef.view.showdebug = true;
4506 if (r_timereport_active)
4507 R_TimeReport("visibility");
4509 r_waterstate.numwaterplanes = 0;
4510 if (r_waterstate.enabled)
4511 R_RenderWaterPlanes();
4514 r_waterstate.numwaterplanes = 0;
4517 if (r_timereport_active)
4518 R_TimeReport("blendview");
4520 GL_Scissor(0, 0, vid.width, vid.height);
4521 GL_ScissorTest(false);
4525 void R_RenderWaterPlanes(void)
4527 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4529 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4530 if (r_timereport_active)
4531 R_TimeReport("waterworld");
4534 // don't let sound skip if going slow
4535 if (r_refdef.scene.extraupdate)
4538 R_DrawModelsAddWaterPlanes();
4539 if (r_timereport_active)
4540 R_TimeReport("watermodels");
4542 if (r_waterstate.numwaterplanes)
4544 R_Water_ProcessPlanes();
4545 if (r_timereport_active)
4546 R_TimeReport("waterscenes");
4550 extern void R_DrawLightningBeams (void);
4551 extern void VM_CL_AddPolygonsToMeshQueue (void);
4552 extern void R_DrawPortals (void);
4553 extern cvar_t cl_locs_show;
4554 static void R_DrawLocs(void);
4555 static void R_DrawEntityBBoxes(void);
4556 void R_RenderScene(void)
4558 r_refdef.stats.renders++;
4562 // don't let sound skip if going slow
4563 if (r_refdef.scene.extraupdate)
4566 R_MeshQueue_BeginScene();
4570 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);
4572 if (cl.csqc_vidvars.drawworld)
4574 // don't let sound skip if going slow
4575 if (r_refdef.scene.extraupdate)
4578 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
4580 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
4581 if (r_timereport_active)
4582 R_TimeReport("worldsky");
4585 if (R_DrawBrushModelsSky() && r_timereport_active)
4586 R_TimeReport("bmodelsky");
4589 R_AnimCache_CacheVisibleEntities();
4591 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
4593 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
4594 if (r_timereport_active)
4595 R_TimeReport("worlddepth");
4597 if (r_depthfirst.integer >= 2)
4599 R_DrawModelsDepth();
4600 if (r_timereport_active)
4601 R_TimeReport("modeldepth");
4604 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
4606 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
4607 if (r_timereport_active)
4608 R_TimeReport("world");
4611 // don't let sound skip if going slow
4612 if (r_refdef.scene.extraupdate)
4616 if (r_timereport_active)
4617 R_TimeReport("models");
4619 // don't let sound skip if going slow
4620 if (r_refdef.scene.extraupdate)
4623 if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4625 R_DrawModelShadows();
4626 R_ResetViewRendering3D();
4627 // don't let sound skip if going slow
4628 if (r_refdef.scene.extraupdate)
4632 R_ShadowVolumeLighting(false);
4633 if (r_timereport_active)
4634 R_TimeReport("rtlights");
4636 // don't let sound skip if going slow
4637 if (r_refdef.scene.extraupdate)
4640 if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
4642 R_DrawModelShadows();
4643 R_ResetViewRendering3D();
4644 // don't let sound skip if going slow
4645 if (r_refdef.scene.extraupdate)
4649 if (cl.csqc_vidvars.drawworld)
4651 R_DrawLightningBeams();
4652 if (r_timereport_active)
4653 R_TimeReport("lightning");
4656 if (r_timereport_active)
4657 R_TimeReport("decals");
4660 if (r_timereport_active)
4661 R_TimeReport("particles");
4664 if (r_timereport_active)
4665 R_TimeReport("explosions");
4668 R_SetupGenericShader(true);
4669 VM_CL_AddPolygonsToMeshQueue();
4671 if (r_refdef.view.showdebug)
4673 if (cl_locs_show.integer)
4676 if (r_timereport_active)
4677 R_TimeReport("showlocs");
4680 if (r_drawportals.integer)
4683 if (r_timereport_active)
4684 R_TimeReport("portals");
4687 if (r_showbboxes.value > 0)
4689 R_DrawEntityBBoxes();
4690 if (r_timereport_active)
4691 R_TimeReport("bboxes");
4695 R_SetupGenericShader(true);
4696 R_MeshQueue_RenderTransparent();
4697 if (r_timereport_active)
4698 R_TimeReport("drawtrans");
4700 R_SetupGenericShader(true);
4702 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))
4704 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
4705 if (r_timereport_active)
4706 R_TimeReport("worlddebug");
4707 R_DrawModelsDebug();
4708 if (r_timereport_active)
4709 R_TimeReport("modeldebug");
4712 R_SetupGenericShader(true);
4714 if (cl.csqc_vidvars.drawworld)
4717 if (r_timereport_active)
4718 R_TimeReport("coronas");
4721 // don't let sound skip if going slow
4722 if (r_refdef.scene.extraupdate)
4725 R_ResetViewRendering2D();
4728 static const unsigned short bboxelements[36] =
4738 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
4741 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
4742 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4743 GL_DepthMask(false);
4744 GL_DepthRange(0, 1);
4745 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4746 R_Mesh_Matrix(&identitymatrix);
4747 R_Mesh_ResetTextureState();
4749 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
4750 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
4751 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
4752 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
4753 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
4754 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
4755 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
4756 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
4757 R_FillColors(color4f, 8, cr, cg, cb, ca);
4758 if (r_refdef.fogenabled)
4760 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
4762 f1 = FogPoint_World(v);
4764 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
4765 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
4766 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
4769 R_Mesh_VertexPointer(vertex3f, 0, 0);
4770 R_Mesh_ColorPointer(color4f, 0, 0);
4771 R_Mesh_ResetTextureState();
4772 R_SetupGenericShader(false);
4773 R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
4776 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4780 prvm_edict_t *edict;
4781 prvm_prog_t *prog_save = prog;
4783 // this function draws bounding boxes of server entities
4787 GL_CullFace(GL_NONE);
4788 R_SetupGenericShader(false);
4792 for (i = 0;i < numsurfaces;i++)
4794 edict = PRVM_EDICT_NUM(surfacelist[i]);
4795 switch ((int)edict->fields.server->solid)
4797 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
4798 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
4799 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
4800 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
4801 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
4802 default: Vector4Set(color, 0, 0, 0, 0.50);break;
4804 color[3] *= r_showbboxes.value;
4805 color[3] = bound(0, color[3], 1);
4806 GL_DepthTest(!r_showdisabledepthtest.integer);
4807 GL_CullFace(r_refdef.view.cullface_front);
4808 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
4814 static void R_DrawEntityBBoxes(void)
4817 prvm_edict_t *edict;
4819 prvm_prog_t *prog_save = prog;
4821 // this function draws bounding boxes of server entities
4827 for (i = 0;i < prog->num_edicts;i++)
4829 edict = PRVM_EDICT_NUM(i);
4830 if (edict->priv.server->free)
4832 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
4833 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
4835 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
4837 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
4838 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
4844 unsigned short nomodelelements[24] =
4856 float nomodelvertex3f[6*3] =
4866 float nomodelcolor4f[6*4] =
4868 0.0f, 0.0f, 0.5f, 1.0f,
4869 0.0f, 0.0f, 0.5f, 1.0f,
4870 0.0f, 0.5f, 0.0f, 1.0f,
4871 0.0f, 0.5f, 0.0f, 1.0f,
4872 0.5f, 0.0f, 0.0f, 1.0f,
4873 0.5f, 0.0f, 0.0f, 1.0f
4876 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
4881 // this is only called once per entity so numsurfaces is always 1, and
4882 // surfacelist is always {0}, so this code does not handle batches
4883 R_Mesh_Matrix(&ent->matrix);
4885 if (ent->flags & EF_ADDITIVE)
4887 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4888 GL_DepthMask(false);
4890 else if (ent->alpha < 1)
4892 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4893 GL_DepthMask(false);
4897 GL_BlendFunc(GL_ONE, GL_ZERO);
4900 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
4901 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4902 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
4903 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4904 R_SetupGenericShader(false);
4905 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4906 if (r_refdef.fogenabled)
4909 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4910 R_Mesh_ColorPointer(color4f, 0, 0);
4911 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4912 f1 = FogPoint_World(org);
4914 for (i = 0, c = color4f;i < 6;i++, c += 4)
4916 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4917 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4918 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4922 else if (ent->alpha != 1)
4924 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4925 R_Mesh_ColorPointer(color4f, 0, 0);
4926 for (i = 0, c = color4f;i < 6;i++, c += 4)
4930 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4931 R_Mesh_ResetTextureState();
4932 R_Mesh_Draw(0, 6, 0, 8, NULL, nomodelelements, 0, 0);
4935 void R_DrawNoModel(entity_render_t *ent)
4938 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4939 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4940 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4942 // R_DrawNoModelCallback(ent, 0);
4945 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4947 vec3_t right1, right2, diff, normal;
4949 VectorSubtract (org2, org1, normal);
4951 // calculate 'right' vector for start
4952 VectorSubtract (r_refdef.view.origin, org1, diff);
4953 CrossProduct (normal, diff, right1);
4954 VectorNormalize (right1);
4956 // calculate 'right' vector for end
4957 VectorSubtract (r_refdef.view.origin, org2, diff);
4958 CrossProduct (normal, diff, right2);
4959 VectorNormalize (right2);
4961 vert[ 0] = org1[0] + width * right1[0];
4962 vert[ 1] = org1[1] + width * right1[1];
4963 vert[ 2] = org1[2] + width * right1[2];
4964 vert[ 3] = org1[0] - width * right1[0];
4965 vert[ 4] = org1[1] - width * right1[1];
4966 vert[ 5] = org1[2] - width * right1[2];
4967 vert[ 6] = org2[0] - width * right2[0];
4968 vert[ 7] = org2[1] - width * right2[1];
4969 vert[ 8] = org2[2] - width * right2[2];
4970 vert[ 9] = org2[0] + width * right2[0];
4971 vert[10] = org2[1] + width * right2[1];
4972 vert[11] = org2[2] + width * right2[2];
4975 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4977 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)
4979 // NOTE: this must not call qglDepthFunc (see r_shadow.c, R_BeginCoronaQuery) thanks to ATI
4983 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4984 fog = FogPoint_World(origin);
4986 R_Mesh_Matrix(&identitymatrix);
4987 GL_BlendFunc(blendfunc1, blendfunc2);
4989 GL_CullFace(GL_NONE);
4991 GL_DepthMask(false);
4992 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4993 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4994 GL_DepthTest(!depthdisable);
4996 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4997 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4998 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4999 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5000 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5001 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5002 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5003 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5004 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5005 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5006 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5007 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5009 R_Mesh_VertexPointer(vertex3f, 0, 0);
5010 R_Mesh_ColorPointer(NULL, 0, 0);
5011 R_Mesh_ResetTextureState();
5012 R_SetupGenericShader(true);
5013 R_Mesh_TexBind(0, R_GetTexture(texture));
5014 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
5015 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
5016 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
5017 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5019 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
5021 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
5022 GL_BlendFunc(blendfunc1, GL_ONE);
5024 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
5025 R_Mesh_Draw(0, 4, 0, 2, NULL, polygonelements, 0, 0);
5029 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5034 VectorSet(v, x, y, z);
5035 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5036 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5038 if (i == mesh->numvertices)
5040 if (mesh->numvertices < mesh->maxvertices)
5042 VectorCopy(v, vertex3f);
5043 mesh->numvertices++;
5045 return mesh->numvertices;
5051 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5055 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5056 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5057 e = mesh->element3i + mesh->numtriangles * 3;
5058 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5060 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5061 if (mesh->numtriangles < mesh->maxtriangles)
5066 mesh->numtriangles++;
5068 element[1] = element[2];
5072 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5076 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5077 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5078 e = mesh->element3i + mesh->numtriangles * 3;
5079 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5081 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5082 if (mesh->numtriangles < mesh->maxtriangles)
5087 mesh->numtriangles++;
5089 element[1] = element[2];
5093 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5094 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5096 int planenum, planenum2;
5099 mplane_t *plane, *plane2;
5101 double temppoints[2][256*3];
5102 // figure out how large a bounding box we need to properly compute this brush
5104 for (w = 0;w < numplanes;w++)
5105 maxdist = max(maxdist, planes[w].dist);
5106 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5107 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5108 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5112 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5113 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5115 if (planenum2 == planenum)
5117 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);
5120 if (tempnumpoints < 3)
5122 // generate elements forming a triangle fan for this polygon
5123 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5127 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)
5129 texturelayer_t *layer;
5130 layer = t->currentlayers + t->currentnumlayers++;
5132 layer->depthmask = depthmask;
5133 layer->blendfunc1 = blendfunc1;
5134 layer->blendfunc2 = blendfunc2;
5135 layer->texture = texture;
5136 layer->texmatrix = *matrix;
5137 layer->color[0] = r * r_refdef.view.colorscale;
5138 layer->color[1] = g * r_refdef.view.colorscale;
5139 layer->color[2] = b * r_refdef.view.colorscale;
5140 layer->color[3] = a;
5143 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5146 index = parms[2] + r_refdef.scene.time * parms[3];
5147 index -= floor(index);
5151 case Q3WAVEFUNC_NONE:
5152 case Q3WAVEFUNC_NOISE:
5153 case Q3WAVEFUNC_COUNT:
5156 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5157 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5158 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5159 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5160 case Q3WAVEFUNC_TRIANGLE:
5162 f = index - floor(index);
5173 return (float)(parms[0] + parms[1] * f);
5176 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5181 matrix4x4_t matrix, temp;
5182 switch(tcmod->tcmod)
5186 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5187 matrix = r_waterscrollmatrix;
5189 matrix = identitymatrix;
5191 case Q3TCMOD_ENTITYTRANSLATE:
5192 // this is used in Q3 to allow the gamecode to control texcoord
5193 // scrolling on the entity, which is not supported in darkplaces yet.
5194 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5196 case Q3TCMOD_ROTATE:
5197 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5198 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5199 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5202 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5204 case Q3TCMOD_SCROLL:
5205 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5207 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5208 w = (int) tcmod->parms[0];
5209 h = (int) tcmod->parms[1];
5210 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5212 idx = (int) floor(f * w * h);
5213 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5215 case Q3TCMOD_STRETCH:
5216 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5217 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5219 case Q3TCMOD_TRANSFORM:
5220 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
5221 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
5222 VectorSet(tcmat + 6, 0 , 0 , 1);
5223 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
5224 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5226 case Q3TCMOD_TURBULENT:
5227 // this is handled in the RSurf_PrepareVertices function
5228 matrix = identitymatrix;
5232 Matrix4x4_Concat(texmatrix, &matrix, &temp);
5235 texture_t *R_GetCurrentTexture(texture_t *t)
5238 const entity_render_t *ent = rsurface.entity;
5239 dp_model_t *model = ent->model;
5240 q3shaderinfo_layer_tcmod_t *tcmod;
5242 if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5243 return t->currentframe;
5244 t->update_lastrenderframe = r_frame;
5245 t->update_lastrenderentity = (void *)ent;
5247 // switch to an alternate material if this is a q1bsp animated material
5249 texture_t *texture = t;
5250 int s = ent->skinnum;
5251 if ((unsigned int)s >= (unsigned int)model->numskins)
5253 if (model->skinscenes)
5255 if (model->skinscenes[s].framecount > 1)
5256 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5258 s = model->skinscenes[s].firstframe;
5261 t = t + s * model->num_surfaces;
5264 // use an alternate animation if the entity's frame is not 0,
5265 // and only if the texture has an alternate animation
5266 if (ent->framegroupblend[0].frame != 0 && t->anim_total[1])
5267 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5269 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5271 texture->currentframe = t;
5274 // update currentskinframe to be a qw skin or animation frame
5275 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"))
5277 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
5279 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
5280 if (developer_loading.integer)
5281 Con_Printf("loading skins/%s\n", r_qwskincache[i]);
5282 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);
5284 t->currentskinframe = r_qwskincache_skinframe[i];
5285 if (t->currentskinframe == NULL)
5286 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5288 else if (t->numskinframes >= 2)
5289 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->shadertime)) % t->numskinframes];
5290 if (t->backgroundnumskinframes >= 2)
5291 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->shadertime)) % t->backgroundnumskinframes];
5293 t->currentmaterialflags = t->basematerialflags;
5294 t->currentalpha = ent->alpha;
5295 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5296 t->currentalpha *= r_wateralpha.value;
5297 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5298 t->currentalpha *= t->r_water_wateralpha;
5299 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5300 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5301 if (!(ent->flags & RENDER_LIGHT))
5302 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5303 else if (rsurface.modeltexcoordlightmap2f == NULL)
5305 // pick a model lighting mode
5306 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
5307 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5309 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5311 if (ent->effects & EF_ADDITIVE)
5312 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5313 else if (t->currentalpha < 1)
5314 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5315 if (ent->effects & EF_DOUBLESIDED)
5316 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5317 if (ent->effects & EF_NODEPTHTEST)
5318 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5319 if (ent->flags & RENDER_VIEWMODEL)
5320 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5321 if (t->backgroundnumskinframes)
5322 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5323 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5325 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5326 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5329 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5331 // there is no tcmod
5332 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5334 t->currenttexmatrix = r_waterscrollmatrix;
5335 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5339 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5340 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5343 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5344 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5345 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5346 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5348 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
5349 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5350 t->glosstexture = r_texture_black;
5351 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5352 t->backgroundglosstexture = r_texture_black;
5353 t->specularpower = r_shadow_glossexponent.value;
5354 // TODO: store reference values for these in the texture?
5355 t->specularscale = 0;
5356 if (r_shadow_gloss.integer > 0)
5358 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5360 if (r_shadow_glossintensity.value > 0)
5362 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5363 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5364 t->specularscale = r_shadow_glossintensity.value;
5367 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5369 t->glosstexture = r_texture_white;
5370 t->backgroundglosstexture = r_texture_white;
5371 t->specularscale = r_shadow_gloss2intensity.value;
5375 // lightmaps mode looks bad with dlights using actual texturing, so turn
5376 // off the colormap and glossmap, but leave the normalmap on as it still
5377 // accurately represents the shading involved
5378 if (gl_lightmaps.integer)
5380 t->basetexture = r_texture_grey128;
5381 t->backgroundbasetexture = NULL;
5382 t->specularscale = 0;
5383 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5386 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
5387 VectorClear(t->dlightcolor);
5388 t->currentnumlayers = 0;
5389 if (t->currentmaterialflags & MATERIALFLAG_WALL)
5392 int blendfunc1, blendfunc2;
5394 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5396 blendfunc1 = GL_SRC_ALPHA;
5397 blendfunc2 = GL_ONE;
5399 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5401 blendfunc1 = GL_SRC_ALPHA;
5402 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5404 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5406 blendfunc1 = t->customblendfunc[0];
5407 blendfunc2 = t->customblendfunc[1];
5411 blendfunc1 = GL_ONE;
5412 blendfunc2 = GL_ZERO;
5414 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5415 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5416 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5417 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5419 // fullbright is not affected by r_refdef.lightmapintensity
5420 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]);
5421 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5422 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]);
5423 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5424 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]);
5428 vec3_t ambientcolor;
5430 // set the color tint used for lights affecting this surface
5431 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
5433 // q3bsp has no lightmap updates, so the lightstylevalue that
5434 // would normally be baked into the lightmap must be
5435 // applied to the color
5436 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5437 if (ent->model->type == mod_brushq3)
5438 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5439 colorscale *= r_refdef.lightmapintensity;
5440 VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5441 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5442 // basic lit geometry
5443 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]);
5444 // add pants/shirt if needed
5445 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5446 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]);
5447 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5448 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]);
5449 // now add ambient passes if needed
5450 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5452 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]);
5453 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5454 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]);
5455 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5456 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]);
5459 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5460 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]);
5461 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5463 // if this is opaque use alpha blend which will darken the earlier
5466 // if this is an alpha blended material, all the earlier passes
5467 // were darkened by fog already, so we only need to add the fog
5468 // color ontop through the fog mask texture
5470 // if this is an additive blended material, all the earlier passes
5471 // were darkened by fog already, and we should not add fog color
5472 // (because the background was not darkened, there is no fog color
5473 // that was lost behind it).
5474 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]);
5478 return t->currentframe;
5481 rsurfacestate_t rsurface;
5483 void R_Mesh_ResizeArrays(int newvertices)
5486 if (rsurface.array_size >= newvertices)
5488 if (rsurface.array_modelvertex3f)
5489 Mem_Free(rsurface.array_modelvertex3f);
5490 rsurface.array_size = (newvertices + 1023) & ~1023;
5491 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5492 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
5493 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
5494 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
5495 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
5496 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
5497 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5498 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5499 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
5500 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
5501 rsurface.array_color4f = base + rsurface.array_size * 27;
5502 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5505 void RSurf_ActiveWorldEntity(void)
5507 dp_model_t *model = r_refdef.scene.worldmodel;
5508 //if (rsurface.entity == r_refdef.scene.worldentity)
5510 rsurface.entity = r_refdef.scene.worldentity;
5511 if (rsurface.array_size < model->surfmesh.num_vertices)
5512 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5513 rsurface.matrix = identitymatrix;
5514 rsurface.inversematrix = identitymatrix;
5515 R_Mesh_Matrix(&identitymatrix);
5516 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
5517 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
5518 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
5519 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
5520 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
5521 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
5522 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
5523 rsurface.frameblend[0].lerp = 1;
5524 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5525 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5526 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5527 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5528 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5529 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5530 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5531 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5532 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5533 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5534 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5535 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5536 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5537 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5538 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5539 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5540 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5541 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5542 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5543 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5544 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5545 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5546 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5547 rsurface.modelelement3i = model->surfmesh.data_element3i;
5548 rsurface.modelelement3s = model->surfmesh.data_element3s;
5549 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5550 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5551 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5552 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5553 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5554 rsurface.modelsurfaces = model->data_surfaces;
5555 rsurface.generatedvertex = false;
5556 rsurface.vertex3f = rsurface.modelvertex3f;
5557 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5558 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5559 rsurface.svector3f = rsurface.modelsvector3f;
5560 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5561 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5562 rsurface.tvector3f = rsurface.modeltvector3f;
5563 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5564 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5565 rsurface.normal3f = rsurface.modelnormal3f;
5566 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5567 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5568 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5571 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5573 dp_model_t *model = ent->model;
5574 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
5576 rsurface.entity = (entity_render_t *)ent;
5577 if (rsurface.array_size < model->surfmesh.num_vertices)
5578 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
5579 rsurface.matrix = ent->matrix;
5580 rsurface.inversematrix = ent->inversematrix;
5581 R_Mesh_Matrix(&rsurface.matrix);
5582 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
5583 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
5584 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
5585 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
5586 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
5587 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
5588 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
5589 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
5590 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
5591 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
5592 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
5593 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
5594 rsurface.basepolygonfactor = r_refdef.polygonfactor;
5595 rsurface.basepolygonoffset = r_refdef.polygonoffset;
5596 if (ent->model->brush.submodel)
5598 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
5599 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
5601 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
5603 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
5605 rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
5606 rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
5607 rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
5608 rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
5610 else if (wanttangents)
5612 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5613 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5614 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5615 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5616 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
5618 else if (wantnormals)
5620 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5621 rsurface.modelsvector3f = NULL;
5622 rsurface.modeltvector3f = NULL;
5623 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5624 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
5628 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
5629 rsurface.modelsvector3f = NULL;
5630 rsurface.modeltvector3f = NULL;
5631 rsurface.modelnormal3f = NULL;
5632 model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
5634 rsurface.modelvertex3f_bufferobject = 0;
5635 rsurface.modelvertex3f_bufferoffset = 0;
5636 rsurface.modelsvector3f_bufferobject = 0;
5637 rsurface.modelsvector3f_bufferoffset = 0;
5638 rsurface.modeltvector3f_bufferobject = 0;
5639 rsurface.modeltvector3f_bufferoffset = 0;
5640 rsurface.modelnormal3f_bufferobject = 0;
5641 rsurface.modelnormal3f_bufferoffset = 0;
5642 rsurface.generatedvertex = true;
5646 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
5647 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
5648 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
5649 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
5650 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
5651 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
5652 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
5653 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
5654 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
5655 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
5656 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
5657 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
5658 rsurface.generatedvertex = false;
5660 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
5661 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
5662 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
5663 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
5664 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
5665 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
5666 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
5667 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
5668 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
5669 rsurface.modelelement3i = model->surfmesh.data_element3i;
5670 rsurface.modelelement3s = model->surfmesh.data_element3s;
5671 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
5672 rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
5673 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
5674 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
5675 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
5676 rsurface.modelsurfaces = model->data_surfaces;
5677 rsurface.vertex3f = rsurface.modelvertex3f;
5678 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5679 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5680 rsurface.svector3f = rsurface.modelsvector3f;
5681 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5682 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5683 rsurface.tvector3f = rsurface.modeltvector3f;
5684 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5685 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5686 rsurface.normal3f = rsurface.modelnormal3f;
5687 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5688 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5689 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5692 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
5693 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
5696 int texturesurfaceindex;
5701 const float *v1, *in_tc;
5703 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
5705 q3shaderinfo_deform_t *deform;
5706 // 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
5707 if (rsurface.generatedvertex)
5709 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
5710 generatenormals = true;
5711 for (i = 0;i < Q3MAXDEFORMS;i++)
5713 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
5715 generatetangents = true;
5716 generatenormals = true;
5718 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
5719 generatenormals = true;
5721 if (generatenormals && !rsurface.modelnormal3f)
5723 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
5724 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
5725 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
5726 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
5728 if (generatetangents && !rsurface.modelsvector3f)
5730 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
5731 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
5732 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
5733 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
5734 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
5735 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
5736 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);
5739 rsurface.vertex3f = rsurface.modelvertex3f;
5740 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
5741 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
5742 rsurface.svector3f = rsurface.modelsvector3f;
5743 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
5744 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
5745 rsurface.tvector3f = rsurface.modeltvector3f;
5746 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
5747 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
5748 rsurface.normal3f = rsurface.modelnormal3f;
5749 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
5750 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
5751 // if vertices are deformed (sprite flares and things in maps, possibly
5752 // water waves, bulges and other deformations), generate them into
5753 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
5754 // (may be static model data or generated data for an animated model, or
5755 // the previous deform pass)
5756 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
5758 switch (deform->deform)
5761 case Q3DEFORM_PROJECTIONSHADOW:
5762 case Q3DEFORM_TEXT0:
5763 case Q3DEFORM_TEXT1:
5764 case Q3DEFORM_TEXT2:
5765 case Q3DEFORM_TEXT3:
5766 case Q3DEFORM_TEXT4:
5767 case Q3DEFORM_TEXT5:
5768 case Q3DEFORM_TEXT6:
5769 case Q3DEFORM_TEXT7:
5772 case Q3DEFORM_AUTOSPRITE:
5773 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5774 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5775 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5776 VectorNormalize(newforward);
5777 VectorNormalize(newright);
5778 VectorNormalize(newup);
5779 // make deformed versions of only the model vertices used by the specified surfaces
5780 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5782 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5783 // a single autosprite surface can contain multiple sprites...
5784 for (j = 0;j < surface->num_vertices - 3;j += 4)
5786 VectorClear(center);
5787 for (i = 0;i < 4;i++)
5788 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5789 VectorScale(center, 0.25f, center);
5790 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
5791 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
5792 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
5793 for (i = 0;i < 4;i++)
5795 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
5796 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5799 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);
5800 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);
5802 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5803 rsurface.vertex3f_bufferobject = 0;
5804 rsurface.vertex3f_bufferoffset = 0;
5805 rsurface.svector3f = rsurface.array_deformedsvector3f;
5806 rsurface.svector3f_bufferobject = 0;
5807 rsurface.svector3f_bufferoffset = 0;
5808 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5809 rsurface.tvector3f_bufferobject = 0;
5810 rsurface.tvector3f_bufferoffset = 0;
5811 rsurface.normal3f = rsurface.array_deformednormal3f;
5812 rsurface.normal3f_bufferobject = 0;
5813 rsurface.normal3f_bufferoffset = 0;
5815 case Q3DEFORM_AUTOSPRITE2:
5816 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
5817 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
5818 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
5819 VectorNormalize(newforward);
5820 VectorNormalize(newright);
5821 VectorNormalize(newup);
5822 // make deformed versions of only the model vertices used by the specified surfaces
5823 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5825 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5826 const float *v1, *v2;
5836 memset(shortest, 0, sizeof(shortest));
5837 // a single autosprite surface can contain multiple sprites...
5838 for (j = 0;j < surface->num_vertices - 3;j += 4)
5840 VectorClear(center);
5841 for (i = 0;i < 4;i++)
5842 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
5843 VectorScale(center, 0.25f, center);
5844 // find the two shortest edges, then use them to define the
5845 // axis vectors for rotating around the central axis
5846 for (i = 0;i < 6;i++)
5848 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
5849 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
5851 Debug_PolygonBegin(NULL, 0);
5852 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
5853 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);
5854 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
5857 l = VectorDistance2(v1, v2);
5858 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
5860 l += (1.0f / 1024.0f);
5861 if (shortest[0].length2 > l || i == 0)
5863 shortest[1] = shortest[0];
5864 shortest[0].length2 = l;
5865 shortest[0].v1 = v1;
5866 shortest[0].v2 = v2;
5868 else if (shortest[1].length2 > l || i == 1)
5870 shortest[1].length2 = l;
5871 shortest[1].v1 = v1;
5872 shortest[1].v2 = v2;
5875 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
5876 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
5878 Debug_PolygonBegin(NULL, 0);
5879 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
5880 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);
5881 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
5884 // this calculates the right vector from the shortest edge
5885 // and the up vector from the edge midpoints
5886 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
5887 VectorNormalize(right);
5888 VectorSubtract(end, start, up);
5889 VectorNormalize(up);
5890 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
5891 VectorSubtract(rsurface.modelorg, center, forward);
5892 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
5893 VectorNegate(forward, forward);
5894 VectorReflect(forward, 0, up, forward);
5895 VectorNormalize(forward);
5896 CrossProduct(up, forward, newright);
5897 VectorNormalize(newright);
5899 Debug_PolygonBegin(NULL, 0);
5900 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);
5901 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
5902 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5906 Debug_PolygonBegin(NULL, 0);
5907 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5908 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5909 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5912 // rotate the quad around the up axis vector, this is made
5913 // especially easy by the fact we know the quad is flat,
5914 // so we only have to subtract the center position and
5915 // measure distance along the right vector, and then
5916 // multiply that by the newright vector and add back the
5918 // we also need to subtract the old position to undo the
5919 // displacement from the center, which we do with a
5920 // DotProduct, the subtraction/addition of center is also
5921 // optimized into DotProducts here
5922 l = DotProduct(right, center);
5923 for (i = 0;i < 4;i++)
5925 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5926 f = DotProduct(right, v1) - l;
5927 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5930 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);
5931 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);
5933 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5934 rsurface.vertex3f_bufferobject = 0;
5935 rsurface.vertex3f_bufferoffset = 0;
5936 rsurface.svector3f = rsurface.array_deformedsvector3f;
5937 rsurface.svector3f_bufferobject = 0;
5938 rsurface.svector3f_bufferoffset = 0;
5939 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5940 rsurface.tvector3f_bufferobject = 0;
5941 rsurface.tvector3f_bufferoffset = 0;
5942 rsurface.normal3f = rsurface.array_deformednormal3f;
5943 rsurface.normal3f_bufferobject = 0;
5944 rsurface.normal3f_bufferoffset = 0;
5946 case Q3DEFORM_NORMAL:
5947 // deform the normals to make reflections wavey
5948 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5950 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5951 for (j = 0;j < surface->num_vertices;j++)
5954 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5955 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5956 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5957 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5958 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5959 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5960 VectorNormalize(normal);
5962 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);
5964 rsurface.svector3f = rsurface.array_deformedsvector3f;
5965 rsurface.svector3f_bufferobject = 0;
5966 rsurface.svector3f_bufferoffset = 0;
5967 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5968 rsurface.tvector3f_bufferobject = 0;
5969 rsurface.tvector3f_bufferoffset = 0;
5970 rsurface.normal3f = rsurface.array_deformednormal3f;
5971 rsurface.normal3f_bufferobject = 0;
5972 rsurface.normal3f_bufferoffset = 0;
5975 // deform vertex array to make wavey water and flags and such
5976 waveparms[0] = deform->waveparms[0];
5977 waveparms[1] = deform->waveparms[1];
5978 waveparms[2] = deform->waveparms[2];
5979 waveparms[3] = deform->waveparms[3];
5980 // this is how a divisor of vertex influence on deformation
5981 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5982 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5983 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5985 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5986 for (j = 0;j < surface->num_vertices;j++)
5988 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5989 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5990 // if the wavefunc depends on time, evaluate it per-vertex
5993 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5994 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5996 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5999 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6000 rsurface.vertex3f_bufferobject = 0;
6001 rsurface.vertex3f_bufferoffset = 0;
6003 case Q3DEFORM_BULGE:
6004 // deform vertex array to make the surface have moving bulges
6005 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6007 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6008 for (j = 0;j < surface->num_vertices;j++)
6010 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6011 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6014 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6015 rsurface.vertex3f_bufferobject = 0;
6016 rsurface.vertex3f_bufferoffset = 0;
6019 // deform vertex array
6020 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6021 VectorScale(deform->parms, scale, waveparms);
6022 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6024 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6025 for (j = 0;j < surface->num_vertices;j++)
6026 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6028 rsurface.vertex3f = rsurface.array_deformedvertex3f;
6029 rsurface.vertex3f_bufferobject = 0;
6030 rsurface.vertex3f_bufferoffset = 0;
6034 // generate texcoords based on the chosen texcoord source
6035 switch(rsurface.texture->tcgen.tcgen)
6038 case Q3TCGEN_TEXTURE:
6039 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6040 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
6041 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
6043 case Q3TCGEN_LIGHTMAP:
6044 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
6045 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6046 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6048 case Q3TCGEN_VECTOR:
6049 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6051 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6052 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)
6054 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6055 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6058 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6059 rsurface.texcoordtexture2f_bufferobject = 0;
6060 rsurface.texcoordtexture2f_bufferoffset = 0;
6062 case Q3TCGEN_ENVIRONMENT:
6063 // make environment reflections using a spheremap
6064 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6066 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6067 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6068 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6069 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6070 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6072 // identical to Q3A's method, but executed in worldspace so
6073 // carried models can be shiny too
6075 float viewer[3], d, reflected[3], worldreflected[3];
6077 VectorSubtract(rsurface.modelorg, vertex, viewer);
6078 // VectorNormalize(viewer);
6080 d = DotProduct(normal, viewer);
6082 reflected[0] = normal[0]*2*d - viewer[0];
6083 reflected[1] = normal[1]*2*d - viewer[1];
6084 reflected[2] = normal[2]*2*d - viewer[2];
6085 // note: this is proportinal to viewer, so we can normalize later
6087 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6088 VectorNormalize(worldreflected);
6090 // note: this sphere map only uses world x and z!
6091 // so positive and negative y will LOOK THE SAME.
6092 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6093 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6096 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6097 rsurface.texcoordtexture2f_bufferobject = 0;
6098 rsurface.texcoordtexture2f_bufferoffset = 0;
6101 // the only tcmod that needs software vertex processing is turbulent, so
6102 // check for it here and apply the changes if needed
6103 // and we only support that as the first one
6104 // (handling a mixture of turbulent and other tcmods would be problematic
6105 // without punting it entirely to a software path)
6106 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6108 amplitude = rsurface.texture->tcmods[0].parms[1];
6109 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6110 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6112 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6113 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)
6115 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6116 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6119 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
6120 rsurface.texcoordtexture2f_bufferobject = 0;
6121 rsurface.texcoordtexture2f_bufferoffset = 0;
6123 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
6124 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6125 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6126 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6129 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
6132 const msurface_t *surface = texturesurfacelist[0];
6133 const msurface_t *surface2;
6138 // TODO: lock all array ranges before render, rather than on each surface
6139 if (texturenumsurfaces == 1)
6141 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6142 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);
6144 else if (r_batchmode.integer == 2)
6146 #define MAXBATCHTRIANGLES 4096
6147 int batchtriangles = 0;
6148 int batchelements[MAXBATCHTRIANGLES*3];
6149 for (i = 0;i < texturenumsurfaces;i = j)
6151 surface = texturesurfacelist[i];
6153 if (surface->num_triangles > MAXBATCHTRIANGLES)
6155 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);
6158 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6159 batchtriangles = surface->num_triangles;
6160 firstvertex = surface->num_firstvertex;
6161 endvertex = surface->num_firstvertex + surface->num_vertices;
6162 for (;j < texturenumsurfaces;j++)
6164 surface2 = texturesurfacelist[j];
6165 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6167 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6168 batchtriangles += surface2->num_triangles;
6169 firstvertex = min(firstvertex, surface2->num_firstvertex);
6170 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6172 surface2 = texturesurfacelist[j-1];
6173 numvertices = endvertex - firstvertex;
6174 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6177 else if (r_batchmode.integer == 1)
6179 for (i = 0;i < texturenumsurfaces;i = j)
6181 surface = texturesurfacelist[i];
6182 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6183 if (texturesurfacelist[j] != surface2)
6185 surface2 = texturesurfacelist[j-1];
6186 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6187 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6188 GL_LockArrays(surface->num_firstvertex, numvertices);
6189 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6194 for (i = 0;i < texturenumsurfaces;i++)
6196 surface = texturesurfacelist[i];
6197 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6198 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);
6203 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6205 int i, planeindex, vertexindex;
6209 r_waterstate_waterplane_t *p, *bestp;
6210 msurface_t *surface;
6211 if (r_waterstate.renderingscene)
6213 for (i = 0;i < texturenumsurfaces;i++)
6215 surface = texturesurfacelist[i];
6216 if (lightmaptexunit >= 0)
6217 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6218 if (deluxemaptexunit >= 0)
6219 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6220 // pick the closest matching water plane
6223 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6226 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6228 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6229 d += fabs(PlaneDiff(vert, &p->plane));
6231 if (bestd > d || !bestp)
6239 if (refractiontexunit >= 0)
6240 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6241 if (reflectiontexunit >= 0)
6242 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6246 if (refractiontexunit >= 0)
6247 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6248 if (reflectiontexunit >= 0)
6249 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6251 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6252 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);
6256 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6260 const msurface_t *surface = texturesurfacelist[0];
6261 const msurface_t *surface2;
6266 // TODO: lock all array ranges before render, rather than on each surface
6267 if (texturenumsurfaces == 1)
6269 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6270 if (deluxemaptexunit >= 0)
6271 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6272 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6273 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);
6275 else if (r_batchmode.integer == 2)
6277 #define MAXBATCHTRIANGLES 4096
6278 int batchtriangles = 0;
6279 int batchelements[MAXBATCHTRIANGLES*3];
6280 for (i = 0;i < texturenumsurfaces;i = j)
6282 surface = texturesurfacelist[i];
6283 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6284 if (deluxemaptexunit >= 0)
6285 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6287 if (surface->num_triangles > MAXBATCHTRIANGLES)
6289 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);
6292 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6293 batchtriangles = surface->num_triangles;
6294 firstvertex = surface->num_firstvertex;
6295 endvertex = surface->num_firstvertex + surface->num_vertices;
6296 for (;j < texturenumsurfaces;j++)
6298 surface2 = texturesurfacelist[j];
6299 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6301 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6302 batchtriangles += surface2->num_triangles;
6303 firstvertex = min(firstvertex, surface2->num_firstvertex);
6304 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6306 surface2 = texturesurfacelist[j-1];
6307 numvertices = endvertex - firstvertex;
6308 R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6311 else if (r_batchmode.integer == 1)
6314 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6315 for (i = 0;i < texturenumsurfaces;i = j)
6317 surface = texturesurfacelist[i];
6318 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6319 if (texturesurfacelist[j] != surface2)
6321 Con_Printf(" %i", j - i);
6324 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6326 for (i = 0;i < texturenumsurfaces;i = j)
6328 surface = texturesurfacelist[i];
6329 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6330 if (deluxemaptexunit >= 0)
6331 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6332 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6333 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6336 Con_Printf(" %i", j - i);
6338 surface2 = texturesurfacelist[j-1];
6339 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6340 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6341 GL_LockArrays(surface->num_firstvertex, numvertices);
6342 R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6350 for (i = 0;i < texturenumsurfaces;i++)
6352 surface = texturesurfacelist[i];
6353 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6354 if (deluxemaptexunit >= 0)
6355 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6356 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6357 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);
6362 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
6365 int texturesurfaceindex;
6366 if (r_showsurfaces.integer == 2)
6368 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6370 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6371 for (j = 0;j < surface->num_triangles;j++)
6373 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
6374 GL_Color(f, f, f, 1);
6375 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6381 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6383 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6384 int k = (int)(((size_t)surface) / sizeof(msurface_t));
6385 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);
6386 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6387 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);
6392 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, msurface_t **texturesurfacelist)
6394 int texturesurfaceindex;
6397 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6399 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6400 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)
6408 rsurface.lightmapcolor4f = rsurface.array_color4f;
6409 rsurface.lightmapcolor4f_bufferobject = 0;
6410 rsurface.lightmapcolor4f_bufferoffset = 0;
6413 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
6415 int texturesurfaceindex;
6419 if (rsurface.lightmapcolor4f)
6421 // generate color arrays for the surfaces in this list
6422 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6424 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6425 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)
6427 f = FogPoint_Model(v);
6437 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6439 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6440 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)
6442 f = FogPoint_Model(v);
6450 rsurface.lightmapcolor4f = rsurface.array_color4f;
6451 rsurface.lightmapcolor4f_bufferobject = 0;
6452 rsurface.lightmapcolor4f_bufferoffset = 0;
6455 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, msurface_t **texturesurfacelist)
6457 int texturesurfaceindex;
6461 if (!rsurface.lightmapcolor4f)
6463 // generate color arrays for the surfaces in this list
6464 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6466 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6467 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)
6469 f = FogPoint_Model(v);
6470 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
6471 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
6472 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
6476 rsurface.lightmapcolor4f = rsurface.array_color4f;
6477 rsurface.lightmapcolor4f_bufferobject = 0;
6478 rsurface.lightmapcolor4f_bufferoffset = 0;
6481 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
6483 int texturesurfaceindex;
6486 if (!rsurface.lightmapcolor4f)
6488 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6490 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6491 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)
6499 rsurface.lightmapcolor4f = rsurface.array_color4f;
6500 rsurface.lightmapcolor4f_bufferobject = 0;
6501 rsurface.lightmapcolor4f_bufferoffset = 0;
6504 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, msurface_t **texturesurfacelist)
6506 int texturesurfaceindex;
6509 if (!rsurface.lightmapcolor4f)
6511 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6513 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6514 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)
6516 c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
6517 c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
6518 c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
6522 rsurface.lightmapcolor4f = rsurface.array_color4f;
6523 rsurface.lightmapcolor4f_bufferobject = 0;
6524 rsurface.lightmapcolor4f_bufferoffset = 0;
6527 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6530 rsurface.lightmapcolor4f = NULL;
6531 rsurface.lightmapcolor4f_bufferobject = 0;
6532 rsurface.lightmapcolor4f_bufferoffset = 0;
6533 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6534 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6535 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6536 GL_Color(r, g, b, a);
6537 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
6540 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6542 // TODO: optimize applyfog && applycolor case
6543 // just apply fog if necessary, and tint the fog color array if necessary
6544 rsurface.lightmapcolor4f = NULL;
6545 rsurface.lightmapcolor4f_bufferobject = 0;
6546 rsurface.lightmapcolor4f_bufferoffset = 0;
6547 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6548 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6549 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6550 GL_Color(r, g, b, a);
6551 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6554 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6556 int texturesurfaceindex;
6560 if (texturesurfacelist[0]->lightmapinfo)
6562 // generate color arrays for the surfaces in this list
6563 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6565 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6566 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
6568 if (surface->lightmapinfo->samples)
6570 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
6571 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
6572 VectorScale(lm, scale, c);
6573 if (surface->lightmapinfo->styles[1] != 255)
6575 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
6577 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
6578 VectorMA(c, scale, lm, c);
6579 if (surface->lightmapinfo->styles[2] != 255)
6582 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
6583 VectorMA(c, scale, lm, c);
6584 if (surface->lightmapinfo->styles[3] != 255)
6587 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
6588 VectorMA(c, scale, lm, c);
6598 rsurface.lightmapcolor4f = rsurface.array_color4f;
6599 rsurface.lightmapcolor4f_bufferobject = 0;
6600 rsurface.lightmapcolor4f_bufferoffset = 0;
6604 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
6605 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
6606 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
6608 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6609 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6610 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6611 GL_Color(r, g, b, a);
6612 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6615 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
6617 int texturesurfaceindex;
6620 float *v, *c, *c2, alpha;
6621 vec3_t ambientcolor;
6622 vec3_t diffusecolor;
6626 VectorCopy(rsurface.modellight_lightdir, lightdir);
6627 f = 0.5f * r_refdef.lightmapintensity;
6628 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
6629 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
6630 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
6631 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
6632 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
6633 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
6635 if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
6637 // generate color arrays for the surfaces in this list
6638 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6640 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6641 int numverts = surface->num_vertices;
6642 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
6643 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
6644 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
6645 // q3-style directional shading
6646 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
6648 if ((f = DotProduct(c2, lightdir)) > 0)
6649 VectorMA(ambientcolor, f, diffusecolor, c);
6651 VectorCopy(ambientcolor, c);
6659 rsurface.lightmapcolor4f = rsurface.array_color4f;
6660 rsurface.lightmapcolor4f_bufferobject = 0;
6661 rsurface.lightmapcolor4f_bufferoffset = 0;
6662 *applycolor = false;
6666 *r = ambientcolor[0];
6667 *g = ambientcolor[1];
6668 *b = ambientcolor[2];
6669 rsurface.lightmapcolor4f = NULL;
6670 rsurface.lightmapcolor4f_bufferobject = 0;
6671 rsurface.lightmapcolor4f_bufferoffset = 0;
6675 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
6677 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
6678 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
6679 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
6680 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
6681 GL_Color(r, g, b, a);
6682 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6685 void RSurf_SetupDepthAndCulling(void)
6687 // submodels are biased to avoid z-fighting with world surfaces that they
6688 // may be exactly overlapping (avoids z-fighting artifacts on certain
6689 // doors and things in Quake maps)
6690 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6691 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
6692 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
6693 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6696 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
6698 // transparent sky would be ridiculous
6699 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6701 R_SetupGenericShader(false);
6704 skyrendernow = false;
6705 // we have to force off the water clipping plane while rendering sky
6709 // restore entity matrix
6710 R_Mesh_Matrix(&rsurface.matrix);
6712 RSurf_SetupDepthAndCulling();
6714 // LordHavoc: HalfLife maps have freaky skypolys so don't use
6715 // skymasking on them, and Quake3 never did sky masking (unlike
6716 // software Quake and software Quake2), so disable the sky masking
6717 // in Quake3 maps as it causes problems with q3map2 sky tricks,
6718 // and skymasking also looks very bad when noclipping outside the
6719 // level, so don't use it then either.
6720 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
6722 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
6723 R_Mesh_ColorPointer(NULL, 0, 0);
6724 R_Mesh_ResetTextureState();
6725 if (skyrendermasked)
6727 R_SetupDepthOrShadowShader();
6728 // depth-only (masking)
6729 GL_ColorMask(0,0,0,0);
6730 // just to make sure that braindead drivers don't draw
6731 // anything despite that colormask...
6732 GL_BlendFunc(GL_ZERO, GL_ONE);
6736 R_SetupGenericShader(false);
6738 GL_BlendFunc(GL_ONE, GL_ZERO);
6740 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6741 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6742 if (skyrendermasked)
6743 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6745 R_Mesh_ResetTextureState();
6746 GL_Color(1, 1, 1, 1);
6749 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6751 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
6754 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
6755 R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
6756 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
6757 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
6758 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
6759 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
6760 if (rsurface.texture->backgroundcurrentskinframe)
6762 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
6763 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
6764 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
6765 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
6767 if(rsurface.texture->colormapping)
6769 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
6770 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
6772 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
6773 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6774 R_Mesh_ColorPointer(NULL, 0, 0);
6776 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6778 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6780 // render background
6781 GL_BlendFunc(GL_ONE, GL_ZERO);
6783 GL_AlphaTest(false);
6785 GL_Color(1, 1, 1, 1);
6786 R_Mesh_ColorPointer(NULL, 0, 0);
6788 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
6789 if (r_glsl_permutation)
6791 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
6792 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6793 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6794 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6795 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6796 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6797 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);
6799 GL_LockArrays(0, 0);
6801 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6802 GL_DepthMask(false);
6803 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
6804 R_Mesh_ColorPointer(NULL, 0, 0);
6806 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
6807 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
6808 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
6811 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
6812 if (!r_glsl_permutation)
6815 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
6816 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
6817 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
6818 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
6819 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
6820 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
6822 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
6824 GL_BlendFunc(GL_ONE, GL_ZERO);
6826 GL_AlphaTest(false);
6830 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6831 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6832 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6835 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
6837 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6838 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);
6840 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
6844 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
6845 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);
6847 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6849 GL_LockArrays(0, 0);
6852 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6854 // OpenGL 1.3 path - anything not completely ancient
6855 int texturesurfaceindex;
6856 qboolean applycolor;
6860 const texturelayer_t *layer;
6861 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6863 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6866 int layertexrgbscale;
6867 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6869 if (layerindex == 0)
6873 GL_AlphaTest(false);
6874 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6877 GL_DepthMask(layer->depthmask && writedepth);
6878 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6879 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
6881 layertexrgbscale = 4;
6882 VectorScale(layer->color, 0.25f, layercolor);
6884 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
6886 layertexrgbscale = 2;
6887 VectorScale(layer->color, 0.5f, layercolor);
6891 layertexrgbscale = 1;
6892 VectorScale(layer->color, 1.0f, layercolor);
6894 layercolor[3] = layer->color[3];
6895 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
6896 R_Mesh_ColorPointer(NULL, 0, 0);
6897 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6898 switch (layer->type)
6900 case TEXTURELAYERTYPE_LITTEXTURE:
6901 memset(&m, 0, sizeof(m));
6902 m.tex[0] = R_GetTexture(r_texture_white);
6903 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6904 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6905 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6906 m.tex[1] = R_GetTexture(layer->texture);
6907 m.texmatrix[1] = layer->texmatrix;
6908 m.texrgbscale[1] = layertexrgbscale;
6909 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
6910 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
6911 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
6912 R_Mesh_TextureState(&m);
6913 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6914 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6915 else if (rsurface.uselightmaptexture)
6916 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6918 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6920 case TEXTURELAYERTYPE_TEXTURE:
6921 memset(&m, 0, sizeof(m));
6922 m.tex[0] = R_GetTexture(layer->texture);
6923 m.texmatrix[0] = layer->texmatrix;
6924 m.texrgbscale[0] = layertexrgbscale;
6925 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6926 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6927 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6928 R_Mesh_TextureState(&m);
6929 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
6931 case TEXTURELAYERTYPE_FOG:
6932 memset(&m, 0, sizeof(m));
6933 m.texrgbscale[0] = layertexrgbscale;
6936 m.tex[0] = R_GetTexture(layer->texture);
6937 m.texmatrix[0] = layer->texmatrix;
6938 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6939 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6940 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6942 R_Mesh_TextureState(&m);
6943 // generate a color array for the fog pass
6944 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6945 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6949 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6950 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)
6952 f = 1 - FogPoint_Model(v);
6953 c[0] = layercolor[0];
6954 c[1] = layercolor[1];
6955 c[2] = layercolor[2];
6956 c[3] = f * layercolor[3];
6959 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6962 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6964 GL_LockArrays(0, 0);
6967 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6969 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6970 GL_AlphaTest(false);
6974 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6976 // OpenGL 1.1 - crusty old voodoo path
6977 int texturesurfaceindex;
6981 const texturelayer_t *layer;
6982 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6984 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6986 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6988 if (layerindex == 0)
6992 GL_AlphaTest(false);
6993 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6996 GL_DepthMask(layer->depthmask && writedepth);
6997 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6998 R_Mesh_ColorPointer(NULL, 0, 0);
6999 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7000 switch (layer->type)
7002 case TEXTURELAYERTYPE_LITTEXTURE:
7003 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7005 // two-pass lit texture with 2x rgbscale
7006 // first the lightmap pass
7007 memset(&m, 0, sizeof(m));
7008 m.tex[0] = R_GetTexture(r_texture_white);
7009 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7010 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7011 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7012 R_Mesh_TextureState(&m);
7013 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7014 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7015 else if (rsurface.uselightmaptexture)
7016 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7018 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7019 GL_LockArrays(0, 0);
7020 // then apply the texture to it
7021 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7022 memset(&m, 0, sizeof(m));
7023 m.tex[0] = R_GetTexture(layer->texture);
7024 m.texmatrix[0] = layer->texmatrix;
7025 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7026 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7027 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7028 R_Mesh_TextureState(&m);
7029 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);
7033 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7034 memset(&m, 0, sizeof(m));
7035 m.tex[0] = R_GetTexture(layer->texture);
7036 m.texmatrix[0] = layer->texmatrix;
7037 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7038 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7039 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7040 R_Mesh_TextureState(&m);
7041 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7042 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);
7044 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);
7047 case TEXTURELAYERTYPE_TEXTURE:
7048 // singletexture unlit texture with transparency support
7049 memset(&m, 0, sizeof(m));
7050 m.tex[0] = R_GetTexture(layer->texture);
7051 m.texmatrix[0] = layer->texmatrix;
7052 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7053 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7054 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7055 R_Mesh_TextureState(&m);
7056 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);
7058 case TEXTURELAYERTYPE_FOG:
7059 // singletexture fogging
7060 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7063 memset(&m, 0, sizeof(m));
7064 m.tex[0] = R_GetTexture(layer->texture);
7065 m.texmatrix[0] = layer->texmatrix;
7066 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7067 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7068 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7069 R_Mesh_TextureState(&m);
7072 R_Mesh_ResetTextureState();
7073 // generate a color array for the fog pass
7074 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7078 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7079 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
7081 f = 1 - FogPoint_Model(v);
7082 c[0] = layer->color[0];
7083 c[1] = layer->color[1];
7084 c[2] = layer->color[2];
7085 c[3] = f * layer->color[3];
7088 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7091 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7093 GL_LockArrays(0, 0);
7096 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7098 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7099 GL_AlphaTest(false);
7103 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7107 GL_AlphaTest(false);
7108 R_Mesh_ColorPointer(NULL, 0, 0);
7109 R_Mesh_ResetTextureState();
7110 R_SetupGenericShader(false);
7112 if(rsurface.texture && rsurface.texture->currentskinframe)
7114 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7115 c[3] *= rsurface.texture->currentalpha;
7125 if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7127 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7128 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7129 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7132 // brighten it up (as texture value 127 means "unlit")
7133 c[0] *= 2 * r_refdef.view.colorscale;
7134 c[1] *= 2 * r_refdef.view.colorscale;
7135 c[2] *= 2 * r_refdef.view.colorscale;
7137 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7138 c[3] *= r_wateralpha.value;
7140 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7142 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7143 GL_DepthMask(false);
7145 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7147 GL_BlendFunc(GL_ONE, GL_ONE);
7148 GL_DepthMask(false);
7150 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7152 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7153 GL_DepthMask(false);
7155 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7157 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7158 GL_DepthMask(false);
7162 GL_BlendFunc(GL_ONE, GL_ZERO);
7163 GL_DepthMask(writedepth);
7166 rsurface.lightmapcolor4f = NULL;
7168 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7170 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7172 rsurface.lightmapcolor4f = NULL;
7173 rsurface.lightmapcolor4f_bufferobject = 0;
7174 rsurface.lightmapcolor4f_bufferoffset = 0;
7176 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7178 qboolean applycolor = true;
7181 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7183 r_refdef.lightmapintensity = 1;
7184 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7185 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7189 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7191 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7192 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7193 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7196 if(!rsurface.lightmapcolor4f)
7197 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7199 RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7200 RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7201 if(r_refdef.fogenabled)
7202 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7204 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7205 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7208 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7211 RSurf_SetupDepthAndCulling();
7212 if (r_showsurfaces.integer == 3)
7213 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7214 else if (r_glsl.integer && gl_support_fragment_shader)
7215 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7216 else if (gl_combine.integer && r_textureunits.integer >= 2)
7217 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7219 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7223 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
7226 RSurf_SetupDepthAndCulling();
7227 if (r_showsurfaces.integer == 3)
7228 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7229 else if (r_glsl.integer && gl_support_fragment_shader)
7230 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7231 else if (gl_combine.integer && r_textureunits.integer >= 2)
7232 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7234 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7238 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7241 int texturenumsurfaces, endsurface;
7243 msurface_t *surface;
7244 msurface_t *texturesurfacelist[1024];
7246 // if the model is static it doesn't matter what value we give for
7247 // wantnormals and wanttangents, so this logic uses only rules applicable
7248 // to a model, knowing that they are meaningless otherwise
7249 if (ent == r_refdef.scene.worldentity)
7250 RSurf_ActiveWorldEntity();
7251 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7252 RSurf_ActiveModelEntity(ent, false, false);
7254 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7256 for (i = 0;i < numsurfaces;i = j)
7259 surface = rsurface.modelsurfaces + surfacelist[i];
7260 texture = surface->texture;
7261 rsurface.texture = R_GetCurrentTexture(texture);
7262 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7263 // scan ahead until we find a different texture
7264 endsurface = min(i + 1024, numsurfaces);
7265 texturenumsurfaces = 0;
7266 texturesurfacelist[texturenumsurfaces++] = surface;
7267 for (;j < endsurface;j++)
7269 surface = rsurface.modelsurfaces + surfacelist[j];
7270 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7272 texturesurfacelist[texturenumsurfaces++] = surface;
7274 // render the range of surfaces
7275 if (ent == r_refdef.scene.worldentity)
7276 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7278 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7280 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7281 GL_AlphaTest(false);
7284 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7286 const entity_render_t *queueentity = r_refdef.scene.worldentity;
7290 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7292 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7294 RSurf_SetupDepthAndCulling();
7295 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7296 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7298 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7300 RSurf_SetupDepthAndCulling();
7301 GL_AlphaTest(false);
7302 R_Mesh_ColorPointer(NULL, 0, 0);
7303 R_Mesh_ResetTextureState();
7304 R_SetupGenericShader(false);
7305 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7307 GL_BlendFunc(GL_ONE, GL_ZERO);
7308 GL_Color(0, 0, 0, 1);
7309 GL_DepthTest(writedepth);
7310 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7312 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7314 RSurf_SetupDepthAndCulling();
7315 GL_AlphaTest(false);
7316 R_Mesh_ColorPointer(NULL, 0, 0);
7317 R_Mesh_ResetTextureState();
7318 R_SetupGenericShader(false);
7319 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7321 GL_BlendFunc(GL_ONE, GL_ZERO);
7323 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7325 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7326 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7327 else if (!rsurface.texture->currentnumlayers)
7329 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7331 // transparent surfaces get pushed off into the transparent queue
7332 int surfacelistindex;
7333 const msurface_t *surface;
7334 vec3_t tempcenter, center;
7335 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7337 surface = texturesurfacelist[surfacelistindex];
7338 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7339 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7340 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7341 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7342 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7347 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7348 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7353 void R_QueueWorldSurfaceList(int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7357 // break the surface list down into batches by texture and use of lightmapping
7358 for (i = 0;i < numsurfaces;i = j)
7361 // texture is the base texture pointer, rsurface.texture is the
7362 // current frame/skin the texture is directing us to use (for example
7363 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7364 // use skin 1 instead)
7365 texture = surfacelist[i]->texture;
7366 rsurface.texture = R_GetCurrentTexture(texture);
7367 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7368 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7370 // if this texture is not the kind we want, skip ahead to the next one
7371 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7375 // simply scan ahead until we find a different texture or lightmap state
7376 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7378 // render the range of surfaces
7379 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
7383 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
7388 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7390 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7392 RSurf_SetupDepthAndCulling();
7393 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7394 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7396 else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7398 RSurf_SetupDepthAndCulling();
7399 GL_AlphaTest(false);
7400 R_Mesh_ColorPointer(NULL, 0, 0);
7401 R_Mesh_ResetTextureState();
7402 R_SetupGenericShader(false);
7403 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7405 GL_BlendFunc(GL_ONE, GL_ZERO);
7406 GL_Color(0, 0, 0, 1);
7407 GL_DepthTest(writedepth);
7408 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7410 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7412 RSurf_SetupDepthAndCulling();
7413 GL_AlphaTest(false);
7414 R_Mesh_ColorPointer(NULL, 0, 0);
7415 R_Mesh_ResetTextureState();
7416 R_SetupGenericShader(false);
7417 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7419 GL_BlendFunc(GL_ONE, GL_ZERO);
7421 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7423 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7424 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7425 else if (!rsurface.texture->currentnumlayers)
7427 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7429 // transparent surfaces get pushed off into the transparent queue
7430 int surfacelistindex;
7431 const msurface_t *surface;
7432 vec3_t tempcenter, center;
7433 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7435 surface = texturesurfacelist[surfacelistindex];
7436 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7437 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7438 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7439 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7440 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7445 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7446 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7451 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
7455 // break the surface list down into batches by texture and use of lightmapping
7456 for (i = 0;i < numsurfaces;i = j)
7459 // texture is the base texture pointer, rsurface.texture is the
7460 // current frame/skin the texture is directing us to use (for example
7461 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
7462 // use skin 1 instead)
7463 texture = surfacelist[i]->texture;
7464 rsurface.texture = R_GetCurrentTexture(texture);
7465 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
7466 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
7468 // if this texture is not the kind we want, skip ahead to the next one
7469 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
7473 // simply scan ahead until we find a different texture or lightmap state
7474 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
7476 // render the range of surfaces
7477 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
7481 float locboxvertex3f[6*4*3] =
7483 1,0,1, 1,0,0, 1,1,0, 1,1,1,
7484 0,1,1, 0,1,0, 0,0,0, 0,0,1,
7485 1,1,1, 1,1,0, 0,1,0, 0,1,1,
7486 0,0,1, 0,0,0, 1,0,0, 1,0,1,
7487 0,0,1, 1,0,1, 1,1,1, 0,1,1,
7488 1,0,0, 0,0,0, 0,1,0, 1,1,0
7491 unsigned short locboxelements[6*2*3] =
7501 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7504 cl_locnode_t *loc = (cl_locnode_t *)ent;
7506 float vertex3f[6*4*3];
7508 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7509 GL_DepthMask(false);
7510 GL_DepthRange(0, 1);
7511 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7513 GL_CullFace(GL_NONE);
7514 R_Mesh_Matrix(&identitymatrix);
7516 R_Mesh_VertexPointer(vertex3f, 0, 0);
7517 R_Mesh_ColorPointer(NULL, 0, 0);
7518 R_Mesh_ResetTextureState();
7519 R_SetupGenericShader(false);
7522 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7523 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7524 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
7525 surfacelist[0] < 0 ? 0.5f : 0.125f);
7527 if (VectorCompare(loc->mins, loc->maxs))
7529 VectorSet(size, 2, 2, 2);
7530 VectorMA(loc->mins, -0.5f, size, mins);
7534 VectorCopy(loc->mins, mins);
7535 VectorSubtract(loc->maxs, loc->mins, size);
7538 for (i = 0;i < 6*4*3;)
7539 for (j = 0;j < 3;j++, i++)
7540 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
7542 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
7545 void R_DrawLocs(void)
7548 cl_locnode_t *loc, *nearestloc;
7550 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
7551 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
7553 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
7554 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
7558 void R_DrawDebugModel(entity_render_t *ent)
7560 int i, j, k, l, flagsmask;
7561 const int *elements;
7563 msurface_t *surface;
7564 dp_model_t *model = ent->model;
7567 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
7569 R_Mesh_ColorPointer(NULL, 0, 0);
7570 R_Mesh_ResetTextureState();
7571 R_SetupGenericShader(false);
7572 GL_DepthRange(0, 1);
7573 GL_DepthTest(!r_showdisabledepthtest.integer);
7574 GL_DepthMask(false);
7575 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7577 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
7579 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
7580 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
7582 if (brush->colbrushf && brush->colbrushf->numtriangles)
7584 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
7585 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);
7586 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
7589 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
7591 if (surface->num_collisiontriangles)
7593 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
7594 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);
7595 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
7600 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7602 if (r_showtris.integer || r_shownormals.integer)
7604 if (r_showdisabledepthtest.integer)
7606 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7607 GL_DepthMask(false);
7611 GL_BlendFunc(GL_ONE, GL_ZERO);
7614 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
7616 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
7618 rsurface.texture = R_GetCurrentTexture(surface->texture);
7619 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
7621 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
7622 if (r_showtris.value > 0)
7624 if (!rsurface.texture->currentlayers->depthmask)
7625 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
7626 else if (ent == r_refdef.scene.worldentity)
7627 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
7629 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
7630 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
7631 R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
7632 R_Mesh_ColorPointer(NULL, 0, 0);
7633 R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
7634 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7635 //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, ent->model->surfmesh.data_element3i, NULL, 0, 0);
7636 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);
7637 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7640 if (r_shownormals.value < 0)
7643 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7645 VectorCopy(rsurface.vertex3f + l * 3, v);
7646 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7647 qglVertex3f(v[0], v[1], v[2]);
7648 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
7649 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7650 qglVertex3f(v[0], v[1], v[2]);
7655 if (r_shownormals.value > 0)
7658 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7660 VectorCopy(rsurface.vertex3f + l * 3, v);
7661 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
7662 qglVertex3f(v[0], v[1], v[2]);
7663 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
7664 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7665 qglVertex3f(v[0], v[1], v[2]);
7670 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7672 VectorCopy(rsurface.vertex3f + l * 3, v);
7673 GL_Color(0, r_refdef.view.colorscale, 0, 1);
7674 qglVertex3f(v[0], v[1], v[2]);
7675 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
7676 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7677 qglVertex3f(v[0], v[1], v[2]);
7682 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
7684 VectorCopy(rsurface.vertex3f + l * 3, v);
7685 GL_Color(0, 0, r_refdef.view.colorscale, 1);
7686 qglVertex3f(v[0], v[1], v[2]);
7687 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
7688 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
7689 qglVertex3f(v[0], v[1], v[2]);
7696 rsurface.texture = NULL;
7700 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
7701 int r_maxsurfacelist = 0;
7702 msurface_t **r_surfacelist = NULL;
7703 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7705 int i, j, endj, f, flagsmask;
7707 dp_model_t *model = r_refdef.scene.worldmodel;
7708 msurface_t *surfaces;
7709 unsigned char *update;
7710 int numsurfacelist = 0;
7714 if (r_maxsurfacelist < model->num_surfaces)
7716 r_maxsurfacelist = model->num_surfaces;
7718 Mem_Free(r_surfacelist);
7719 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7722 RSurf_ActiveWorldEntity();
7724 surfaces = model->data_surfaces;
7725 update = model->brushq1.lightmapupdateflags;
7727 // update light styles on this submodel
7728 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7730 model_brush_lightstyleinfo_t *style;
7731 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7733 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7735 int *list = style->surfacelist;
7736 style->value = r_refdef.scene.lightstylevalue[style->style];
7737 for (j = 0;j < style->numsurfaces;j++)
7738 update[list[j]] = true;
7743 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7747 R_DrawDebugModel(r_refdef.scene.worldentity);
7748 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7754 rsurface.uselightmaptexture = false;
7755 rsurface.texture = NULL;
7756 rsurface.rtlight = NULL;
7758 // add visible surfaces to draw list
7759 for (i = 0;i < model->nummodelsurfaces;i++)
7761 j = model->sortedmodelsurfaces[i];
7762 if (r_refdef.viewcache.world_surfacevisible[j])
7763 r_surfacelist[numsurfacelist++] = surfaces + j;
7765 // update lightmaps if needed
7767 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7768 if (r_refdef.viewcache.world_surfacevisible[j])
7770 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
7771 // don't do anything if there were no surfaces
7772 if (!numsurfacelist)
7774 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7777 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7778 GL_AlphaTest(false);
7780 // add to stats if desired
7781 if (r_speeds.integer && !skysurfaces && !depthonly)
7783 r_refdef.stats.world_surfaces += numsurfacelist;
7784 for (j = 0;j < numsurfacelist;j++)
7785 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
7787 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7790 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
7792 int i, j, endj, f, flagsmask;
7794 dp_model_t *model = ent->model;
7795 msurface_t *surfaces;
7796 unsigned char *update;
7797 int numsurfacelist = 0;
7801 if (r_maxsurfacelist < model->num_surfaces)
7803 r_maxsurfacelist = model->num_surfaces;
7805 Mem_Free(r_surfacelist);
7806 r_surfacelist = (msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
7809 // if the model is static it doesn't matter what value we give for
7810 // wantnormals and wanttangents, so this logic uses only rules applicable
7811 // to a model, knowing that they are meaningless otherwise
7812 if (ent == r_refdef.scene.worldentity)
7813 RSurf_ActiveWorldEntity();
7814 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7815 RSurf_ActiveModelEntity(ent, false, false);
7817 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
7819 surfaces = model->data_surfaces;
7820 update = model->brushq1.lightmapupdateflags;
7822 // update light styles
7823 if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
7825 model_brush_lightstyleinfo_t *style;
7826 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
7828 if (style->value != r_refdef.scene.lightstylevalue[style->style])
7830 int *list = style->surfacelist;
7831 style->value = r_refdef.scene.lightstylevalue[style->style];
7832 for (j = 0;j < style->numsurfaces;j++)
7833 update[list[j]] = true;
7838 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
7842 R_DrawDebugModel(ent);
7843 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7849 rsurface.uselightmaptexture = false;
7850 rsurface.texture = NULL;
7851 rsurface.rtlight = NULL;
7853 // add visible surfaces to draw list
7854 for (i = 0;i < model->nummodelsurfaces;i++)
7855 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
7856 // don't do anything if there were no surfaces
7857 if (!numsurfacelist)
7859 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7862 // update lightmaps if needed
7864 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
7866 R_BuildLightMap(ent, surfaces + j);
7867 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
7868 GL_AlphaTest(false);
7870 // add to stats if desired
7871 if (r_speeds.integer && !skysurfaces && !depthonly)
7873 r_refdef.stats.entities_surfaces += numsurfacelist;
7874 for (j = 0;j < numsurfacelist;j++)
7875 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
7877 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity